├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── sleex1.png
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── PKGBUILD
├── README.md
├── preview.mp4
├── sleex-packages
├── .gitignore
├── README.md
├── build-all.sh
├── sleex-bibata-modern-classic-bin
│ └── PKGBUILD
└── sleex-microtex-git
│ ├── .gitignore
│ └── PKGBUILD
├── sleex-user-config
├── .gitignore
├── PKGBUILD
├── README.md
└── src
│ └── .config
│ ├── Kvantum
│ ├── Colloid
│ │ ├── Colloid.kvconfig
│ │ ├── Colloid.svg
│ │ ├── ColloidDark.kvconfig
│ │ └── ColloidDark.svg
│ ├── MaterialAdw
│ │ ├── MaterialAdw.kvconfig
│ │ └── MaterialAdw.svg
│ └── kvantum.kvconfig
│ ├── anyrun
│ ├── config.ron
│ └── style.css
│ ├── chrome-flags.conf
│ ├── code-flags.conf
│ ├── fish
│ ├── auto-Hypr.fish
│ ├── config.fish
│ └── fish_variables
│ ├── fontconfig
│ └── conf.d
│ ├── foot
│ └── foot.ini
│ ├── fuzzel
│ ├── fuzzel.ini
│ └── fuzzel_theme.ini
│ ├── hypr
│ ├── apps.conf
│ ├── custom
│ │ ├── env.conf
│ │ ├── execs.conf
│ │ ├── general.conf
│ │ ├── keybinds.conf
│ │ ├── rules.conf
│ │ └── scripts
│ │ │ └── __restore_video_wallpaper.sh
│ ├── hypridle.conf
│ ├── hyprland.conf
│ ├── hyprland
│ │ ├── colors.conf
│ │ ├── env.conf
│ │ ├── execs.conf
│ │ ├── general.conf
│ │ ├── keybinds_fr.conf
│ │ ├── keybinds_us.conf
│ │ └── rules.conf
│ ├── monitors.conf
│ └── workspaces.conf
│ ├── kde-material-you-colors
│ └── config.conf
│ ├── kdeglobals
│ ├── kitty
│ ├── kitty.conf
│ ├── scroll_mark.py
│ └── search.py
│ ├── matugen
│ ├── config.toml
│ ├── scripts
│ │ └── least_busy_region.py
│ └── templates
│ │ ├── ags
│ │ ├── _material.scss
│ │ ├── sourceviewtheme-light.xml
│ │ └── sourceviewtheme.xml
│ │ ├── colors.json
│ │ ├── discord.css
│ │ ├── fuzzel
│ │ └── fuzzel_theme.ini
│ │ ├── gtk
│ │ └── gtk-colors.css
│ │ ├── hyprland
│ │ ├── colors.conf
│ │ └── hyprlock.conf
│ │ ├── kde
│ │ ├── color.txt
│ │ └── kde-material-you-colors-wrapper.sh
│ │ ├── wallpaper.txt
│ │ └── zed.json
│ ├── mpv
│ └── mpv.conf
│ ├── qt5ct
│ └── qt5ct.conf
│ ├── qt6ct
│ └── qt6ct.conf
│ ├── starship.toml
│ ├── thorium-flags.conf
│ ├── wlogout
│ ├── layout
│ └── style.css
│ ├── xdg-desktop-portal
│ └── hyprland-portals.conf
│ └── zshrc.d
│ ├── auto-Hypr.sh
│ ├── dots-hyprland.zsh
│ └── shortcuts.zsh
└── src
├── bin
├── fuzzel-emoji
├── rubyshot
└── sleex
└── share
├── sleex
├── .gitignore
├── CMakeLists.txt
├── GlobalStates.qml
├── ReloadPopup.qml
├── assets
│ ├── icons
│ │ ├── ai-openai-symbolic.svg
│ │ ├── arch-symbolic.svg
│ │ ├── axos-symbolic.svg
│ │ ├── cachyos-symbolic.svg
│ │ ├── cloudflare-dns-symbolic.svg
│ │ ├── crosshair-symbolic.svg
│ │ ├── debian-symbolic.svg
│ │ ├── deepseek-symbolic.svg
│ │ ├── desktop-symbolic.svg
│ │ ├── endeavouros-symbolic.svg
│ │ ├── fedora-symbolic.svg
│ │ ├── flatpak-symbolic.svg
│ │ ├── github-symbolic.svg
│ │ ├── google-gemini-symbolic.svg
│ │ ├── linux-symbolic.svg
│ │ ├── microsoft-symbolic.svg
│ │ ├── mona-loading.gif
│ │ ├── nixos-symbolic.svg
│ │ ├── ollama-symbolic.svg
│ │ ├── openai-symbolic.svg
│ │ ├── openrouter-symbolic.svg
│ │ ├── spark-symbolic.svg
│ │ └── ubuntu-symbolic.svg
│ ├── logo
│ │ ├── 1024px
│ │ │ ├── black.png
│ │ │ ├── dark.png
│ │ │ ├── light.png
│ │ │ └── white.png
│ │ ├── 128px
│ │ │ ├── black.png
│ │ │ ├── dark.png
│ │ │ ├── light.png
│ │ │ └── white.png
│ │ ├── 256px
│ │ │ ├── black.png
│ │ │ ├── dark.png
│ │ │ ├── light.png
│ │ │ └── white.png
│ │ ├── 512px
│ │ │ ├── black.png
│ │ │ ├── dark.png
│ │ │ ├── light.png
│ │ │ └── white.png
│ │ ├── logotype
│ │ │ ├── black.png
│ │ │ ├── dark.png
│ │ │ ├── light.png
│ │ │ └── white.png
│ │ ├── svg
│ │ │ ├── black.svg
│ │ │ ├── dark.svg
│ │ │ ├── light.svg
│ │ │ └── white.svg
│ │ └── svg_logotype
│ │ │ ├── dark.svg
│ │ │ └── light.svg
│ └── sounds
│ │ └── battery
│ │ ├── 01_full.wav
│ │ ├── 02_plug.wav
│ │ ├── 02_unplug.wav
│ │ ├── 04_warn.wav
│ │ └── 05_critical.wav
├── modules
│ ├── background
│ │ ├── Background.qml
│ │ ├── Clock.qml
│ │ ├── Quote.qml
│ │ └── Watermark.qml
│ ├── bar
│ │ ├── ActiveWindow.qml
│ │ ├── AudioOsd.qml
│ │ ├── Bar.qml
│ │ ├── BarGroupCenter.qml
│ │ ├── BarGroupL.qml
│ │ ├── BarGroupR.qml
│ │ ├── BatteryIndicator.qml
│ │ ├── BatteryIndicator.qml.back
│ │ ├── BatteryPopup.qml
│ │ ├── BluetoothIndicator.qml
│ │ ├── BrightnessOsd.qml
│ │ ├── BtPopup.qml
│ │ ├── CircleUtilButton.qml
│ │ ├── ClockWidget.qml
│ │ ├── HyprlandXkbIndicator.qml
│ │ ├── NotifIndicator.qml
│ │ ├── Resource.qml
│ │ ├── Resources.qml
│ │ ├── ScrollHint.qml
│ │ ├── StyledPopup.qml
│ │ ├── SysTray.qml
│ │ ├── SysTrayItem.qml
│ │ ├── SysTrayMenu.qml
│ │ ├── SysTrayMenuEntry.qml
│ │ └── Workspaces.qml
│ ├── cheatsheet
│ │ ├── Cheatsheet.qml
│ │ └── CheatsheetKeybinds.qml
│ ├── common
│ │ ├── Appearance.qml
│ │ ├── Config.qml
│ │ ├── ConfigOptions.qml
│ │ ├── Directories.qml
│ │ ├── Persistent.qml
│ │ ├── PersistentStates.qml
│ │ ├── StyledComboBox.qml
│ │ ├── functions
│ │ │ ├── ColorUtils.qml
│ │ │ ├── FileUtils.qml
│ │ │ ├── Fuzzy.qml
│ │ │ ├── Lavendist.qml
│ │ │ ├── ObjectUtils.qml
│ │ │ ├── StringUtils.qml
│ │ │ ├── fuzzysort.js
│ │ │ ├── levendist.js
│ │ │ └── object_utils.js
│ │ └── widgets
│ │ │ ├── AudioDeviceSelectorButton.qml
│ │ │ ├── ButtonGroup.qml
│ │ │ ├── CachingImage.qml
│ │ │ ├── CircularProgress.qml
│ │ │ ├── CliphistImage.qml
│ │ │ ├── ClippedFilledCircularProgress.qml
│ │ │ ├── ClippingRectangle.qml
│ │ │ ├── ConfigRow.qml
│ │ │ ├── ConfigSelectionArray.qml
│ │ │ ├── ConfigSpinBox.qml
│ │ │ ├── ConfigSwitch.qml
│ │ │ ├── ContentPage.qml
│ │ │ ├── ContentSection.qml
│ │ │ ├── ContentSubsection.qml
│ │ │ ├── ContentSubsectionLabel.qml
│ │ │ ├── CustomIcon.qml
│ │ │ ├── DialogButton.qml
│ │ │ ├── DragManager.qml
│ │ │ ├── Favicon.qml
│ │ │ ├── FloatingActionButton.qml
│ │ │ ├── FlowButtonGroup.qml
│ │ │ ├── GroupButton.qml
│ │ │ ├── KeyboardKey.qml
│ │ │ ├── LightDarkPreferenceButton.qml
│ │ │ ├── MaterialSymbol.qml
│ │ │ ├── MaterialTextField.qml
│ │ │ ├── MenuButton.qml
│ │ │ ├── NavRailButton.qml
│ │ │ ├── NavigationRail.qml
│ │ │ ├── NavigationRailButton.qml
│ │ │ ├── NavigationRailExpandButton.qml
│ │ │ ├── NavigationRailTabArray.qml
│ │ │ ├── NotificationActionButton.qml
│ │ │ ├── NotificationAppIcon.qml
│ │ │ ├── NotificationGroup.qml
│ │ │ ├── NotificationGroupExpandButton.qml
│ │ │ ├── NotificationItem.qml
│ │ │ ├── NotificationListView.qml
│ │ │ ├── PointingHandInteraction.qml
│ │ │ ├── PointingHandLinkHover.qml
│ │ │ ├── PopupToolTip.qml
│ │ │ ├── PrimaryTabBar.qml
│ │ │ ├── PrimaryTabButton.qml
│ │ │ ├── Revealer.qml
│ │ │ ├── RippleButton.qml
│ │ │ ├── RippleButtonWithIcon.qml
│ │ │ ├── RoundCorner.qml
│ │ │ ├── ScrollEdgeFade.qml
│ │ │ ├── SecondaryTabButton.qml
│ │ │ ├── SelectionDialog.qml
│ │ │ ├── SelectionGroupButton.qml
│ │ │ ├── StyledBusyIndicator.qml
│ │ │ ├── StyledComboBox.qml
│ │ │ ├── StyledFlickable.qml
│ │ │ ├── StyledLabel.qml
│ │ │ ├── StyledListView.qml
│ │ │ ├── StyledProgressBar.qml
│ │ │ ├── StyledRadioButton.qml
│ │ │ ├── StyledRectangularShadow.qml
│ │ │ ├── StyledScrollBar.qml
│ │ │ ├── StyledSlider.qml
│ │ │ ├── StyledSpinBox.qml
│ │ │ ├── StyledSwitch.qml
│ │ │ ├── StyledText.qml
│ │ │ ├── StyledTextArea.qml
│ │ │ ├── StyledTextInput.qml
│ │ │ ├── StyledToolTip.qml
│ │ │ ├── StyledToolTipContent.qml
│ │ │ ├── VerticalButtonGroup.qml
│ │ │ ├── VolumeMixer.qml
│ │ │ ├── WaveVisualizer.qml
│ │ │ └── notification_utils.js
│ ├── dashboard
│ │ ├── AiWidgetGroup.qml
│ │ ├── Dashboard.qml
│ │ ├── DashboardTabs.qml
│ │ ├── HomeWidgetGroup.qml
│ │ ├── TodoWidgetGroup.qml
│ │ ├── ai
│ │ │ ├── AiChat.qml
│ │ │ ├── ApiCommandButton.qml
│ │ │ ├── ApiInputBoxIndicator.qml
│ │ │ ├── DescriptionBox.qml
│ │ │ └── aiChat
│ │ │ │ ├── AiMessage.qml
│ │ │ │ ├── AiMessageControlButton.qml
│ │ │ │ ├── AnnotationSourceButton.qml
│ │ │ │ ├── AttachedFileIndicator.qml
│ │ │ │ ├── MessageCodeBlock.qml
│ │ │ │ ├── MessageTextBlock.qml
│ │ │ │ ├── MessageThinkBlock.qml
│ │ │ │ └── SearchQueryButton.qml
│ │ ├── calendar
│ │ │ ├── CalendarDayButton.qml
│ │ │ ├── CalendarHeaderButton.qml
│ │ │ ├── CalendarWidget.qml
│ │ │ ├── GhCalendar.qml
│ │ │ └── calendar_layout.js
│ │ ├── notifications
│ │ │ ├── NotificationList.qml
│ │ │ └── NotificationStatusButton.qml
│ │ ├── quickToggles
│ │ │ ├── BluetoothToggle.qml
│ │ │ ├── GameMode.qml
│ │ │ ├── IdleInhibitor.qml
│ │ │ ├── NetworkToggle.qml
│ │ │ ├── NightLight.qml
│ │ │ └── QuickToggleButton.qml
│ │ ├── todo
│ │ │ ├── TaskList.qml
│ │ │ ├── TodoItemActionButton.qml
│ │ │ └── TodoWidget.qml
│ │ └── weather
│ │ │ ├── Weather.qml
│ │ │ └── WeatherOff.qml
│ ├── dock
│ │ ├── Dock.qml
│ │ ├── DockAppButton.qml
│ │ ├── DockApps.qml
│ │ ├── DockButton.qml
│ │ └── DockSeparator.qml
│ ├── lockscreen
│ │ ├── Lock.qml
│ │ ├── LockContext.qml
│ │ ├── LockSurface.qml
│ │ └── pam
│ │ │ └── password.conf
│ ├── mediaControls
│ │ ├── MediaControls.qml
│ │ ├── PlayerControl.qml
│ │ └── PlayerControlBlank.qml
│ ├── notificationPopup
│ │ └── NotificationPopup.qml
│ ├── onScreenDisplay
│ │ ├── OnScreenDisplayBrightness.qml
│ │ ├── OnScreenDisplayVolume.qml
│ │ └── OsdValueIndicator.qml
│ ├── overview
│ │ ├── Overview.qml
│ │ ├── OverviewWidget.qml
│ │ ├── OverviewWindow.qml
│ │ ├── SearchItem.qml
│ │ └── SearchWidget.qml
│ ├── screenCorners
│ │ └── ScreenCorners.qml
│ ├── session
│ │ ├── Session.qml
│ │ └── SessionActionButton.qml
│ ├── settings
│ │ ├── About.qml
│ │ ├── BehaviorConfig.qml
│ │ ├── Bluetooth.qml
│ │ ├── Display.qml
│ │ ├── Interface.qml
│ │ ├── Privacy.qml
│ │ ├── Sound.qml
│ │ ├── Style.qml
│ │ ├── Wifi.qml
│ │ └── displaySettings
│ │ │ ├── DisplaySettings.qml
│ │ │ └── MonitorItem.qml
│ ├── sidebarLeft
│ │ ├── AiChat.qml
│ │ ├── ApiCommandButton.qml
│ │ ├── ApiInputBoxIndicator.qml
│ │ ├── DescriptionBox.qml
│ │ ├── SidebarLeft.qml
│ │ ├── SidebarLeftContent.qml
│ │ └── aiChat
│ │ │ ├── AiMessage.qml
│ │ │ ├── AiMessageControlButton.qml
│ │ │ ├── AnnotationSourceButton.qml
│ │ │ ├── AttachedFileIndicator.qml
│ │ │ ├── MessageCodeBlock.qml
│ │ │ ├── MessageTextBlock.qml
│ │ │ ├── MessageThinkBlock.qml
│ │ │ └── SearchQueryButton.qml
│ └── wallpaperSelector
│ │ └── WallpaperSelector.qml
├── plugins
│ ├── CMakeLists.txt
│ └── src
│ │ └── Sleex
│ │ ├── CMakeLists.txt
│ │ └── services
│ │ ├── CMakeLists.txt
│ │ ├── bluetooth.cpp
│ │ ├── bluetooth.hpp
│ │ ├── brightness.cpp
│ │ ├── brightness.hpp
│ │ ├── displays.hpp
│ │ ├── meta_types
│ │ └── qt6sleex-services_metatypes.json
│ │ ├── monitor.cpp
│ │ ├── monitor.hpp
│ │ ├── network.cpp
│ │ ├── network.hpp
│ │ ├── plugin.cpp
│ │ ├── qmltypes
│ │ └── sleex-services_foreign_types.txt
│ │ ├── resourceUsage.cpp
│ │ ├── resourceUsage.hpp
│ │ ├── sleex-servicesplugin_Sleex_ServicesPlugin.cpp
│ │ └── sleex-servicesplugin_Sleex_ServicesPlugin_in.cpp
├── qml
│ └── Sleex
│ │ └── Services
│ │ ├── qmldir
│ │ └── sleex-services_qml_module_dir_map.qrc
├── scripts
│ ├── ai
│ │ └── show-installed-ollama-models.sh
│ ├── cava
│ │ └── raw_output_config.txt
│ ├── colors
│ │ ├── applycolor.sh
│ │ ├── generate_colors_material.py
│ │ ├── scheme_for_image.py
│ │ ├── switchwall.sh
│ │ └── term_gen_colors.sh
│ ├── firstRun.sh
│ ├── grimblast.sh
│ ├── hyprland
│ │ ├── get_keybinds.py
│ │ └── workspace_action.sh
│ ├── insomnia
│ │ └── insomnia.sh
│ ├── kvantum
│ │ ├── adwsvg.py
│ │ ├── adwsvgDark.py
│ │ ├── changeAdwColors.py
│ │ └── materialQT.sh
│ ├── record-script.sh
│ ├── templates
│ │ ├── gtk
│ │ │ └── gtk-colors.css
│ │ ├── term_emus
│ │ │ ├── alacritty.tpl
│ │ │ ├── foot.tpl
│ │ │ ├── ghostty.tpl
│ │ │ ├── kitty.tpl
│ │ │ ├── wezterm.tpl
│ │ │ └── zellij.tpl
│ │ └── terminal
│ │ │ ├── scheme-base.json
│ │ │ ├── scheme-monochrome.json
│ │ │ └── sequences.txt
│ ├── terminal
│ │ ├── scheme-base.json
│ │ └── sequences.txt
│ └── wayland-idle-inhibitor.py
├── services
│ ├── Ai.qml
│ ├── AiMessageData.qml
│ ├── AppSearch.qml
│ ├── Audio.qml
│ ├── Battery.qml
│ ├── Brightness.qml
│ ├── Cliphist.qml
│ ├── ConfigLoader.qml
│ ├── DateTime.qml
│ ├── Emojis.qml
│ ├── FirstRunExperience.qml
│ ├── Github.qml
│ ├── HyprlandData.qml
│ ├── HyprlandKeybinds.qml
│ ├── HyprlandXkb.qml
│ ├── KeyringStorage.qml
│ ├── LatexRenderer.qml
│ ├── MaterialThemeLoader.qml
│ ├── Monitors.qml
│ ├── MprisController.qml
│ ├── Network.qml
│ ├── NightLight.qml
│ ├── Notifications.qml
│ ├── PersistentStateManager.qml
│ ├── Quotes.qml
│ ├── SystemInfo.qml
│ ├── Todo.qml
│ ├── Wallpapers.qml
│ ├── Weather.qml
│ ├── Ydotool.qml
│ └── ai
│ │ ├── AiMessageData.qml
│ │ ├── AiModel.qml
│ │ ├── ApiStrategy.qml
│ │ ├── GeminiApiStrategy.qml
│ │ ├── MistralApiStrategy.qml
│ │ └── OpenAiApiStrategy.qml
├── settings.qml
├── shell.qml
├── wallpapers
│ ├── Glooe.png
│ ├── Gloow.png
│ ├── RenderBall.png
│ ├── Robohand.png
│ ├── SleexBlackSE.png
│ ├── SleexFour.png
│ ├── SleexFourB.png
│ ├── SleexFourSE.png
│ ├── SleexOne.png
│ ├── SleexThree.png
│ ├── SleexThreeSE.png
│ ├── SleexTwo.png
│ ├── SleexTwoSE.png
│ ├── sakura.png
│ └── skyline.jpg
└── welcome.qml
└── wayland-sessions
└── sleex.desktop
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Version (please complete the following information):**
27 | - OS: [e.g. AxOS]
28 | - Sleex version: [e.g 1.15-1]
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/sleex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/.github/sleex1.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.tar.zst
2 | pkg/
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Sleex
2 |
3 | **Thanks for your interest in contributing to Sleex!**
4 | This project exists because of passionate people like you who want to build a clean, modern, and hackable desktop environment. Contributions of all kinds are welcome—code, documentation, bug reports, or even just good ideas.
5 |
6 | ## 🛠 How to Contribute
7 | ### 1. Reporting Issues
8 | - Use the [issue tracker](https://github.com/axos-project/sleex/issues)
9 | - Be clear and descriptive: explain what you expected to happen vs. what actually happened.
10 | - Include logs, screenshots, or configs if relevant.
11 | - Use labels when possible (bug, enhancement, docs, etc.).
12 |
13 | ### 2. Suggesting Features
14 |
15 | - Check if the idea already exists in the issues or discussions.
16 | - Open a new issue with the `enhancement` label.
17 | - Keep it realistic
18 |
19 | ### 3. Submitting Code
20 |
21 | - Fork the repo and create a feature branch:
22 |
23 | ```
24 | git checkout -b feature/your-feature
25 | ```
26 | - Test your changes on a real session before submitting.
27 | - Commit messages should be short and meaningful:
28 |
29 | ```
30 | feat: add brightness plugin
31 | fix: resolve crash on startup
32 | ```
33 | - Squash if too many commits have the same purpose
34 |
35 | ### 4. Pull Requests
36 |
37 | - PRs should be focused (one feature/fix per PR).
38 | - Reference the related issue if one exists (Fixes #123).
39 | - Write a summary of what your PR does.
40 | - Expect feedback—reviews are collaborative, not personal.
41 |
42 | ## 🧪 Testing
43 |
44 | - Test locally on Wayland with **Quickshell + Sleex** running.
45 | - Check that no regressions occur in core features (panels, windows, keybindings).
46 | - Automated tests are limited, so manual testing matters a lot.
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Sleex is the third desktop environement of AxOS. It is based on Hyprland with Quickshell.
6 |
7 | ## Features
8 | - Fast and lightweight
9 | - AI chat integration with external providers (Gemini, OpenAI...)
10 | - Smooth animations
11 | - Tiling window management for seamless multitasking
12 | - Adaptative color scheme based on the wallpaper
13 | - Ready to use
14 | - Multiple available built in tools
15 | - Looks good
16 |
17 | | |
18 | |------|
19 | |  |
20 |
21 | ## Installation
22 |
23 | > [!IMPORTANT]
24 | > If you already have an hyprland config, this will erase it.
25 |
26 | If you are using AxOS, you can simply use epsilon:
27 | ```
28 | epsi i sleex
29 | ```
30 |
31 | # Cross distro
32 |
33 | - Clone this repo
34 | - Build every sleex meta-packages in `sleex-packages` then install them
35 | - Build the user configuration in the `sleex-user-config` and copy the user files to your home dir with `cp -r /etc/skel/.config/* ~/.config`.
36 | - Build and install the main package
37 |
38 | Then, you can start sleex by selecting the sleex session on your greeter
39 |
40 | ## License
41 | Sleex is licensed under the GNU General Public License v3.0
42 |
43 | ## Special thanks
44 | - [@end-4](https://github.com/end-4/): Great inspiration | Sleex is based on his work
45 | - [@xHyperVoid](https://github.com/xHyperVoid): Designer | Made the logo and the wallpapers
46 |
--------------------------------------------------------------------------------
/preview.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/preview.mp4
--------------------------------------------------------------------------------
/sleex-packages/.gitignore:
--------------------------------------------------------------------------------
1 | /*/*.tar.*
2 | /*/pkg/
3 | /*/src/
4 | out/
--------------------------------------------------------------------------------
/sleex-packages/README.md:
--------------------------------------------------------------------------------
1 | # Sleex packages
2 |
3 | Dependency wheel meta-packages for Sleex.
4 |
--------------------------------------------------------------------------------
/sleex-packages/build-all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | OUTDIR="./out"
6 | mkdir -p "$OUTDIR"
7 |
8 | GREEN='\033[0;32m'
9 | NC='\033[0m' # No Color
10 |
11 | for dir in */; do
12 | [[ -f "${dir}/PKGBUILD" ]] || continue
13 | echo -e "${GREEN}==> Building package in $dir${NC}"
14 | pushd "$dir" > /dev/null
15 | makepkg -fcs --noconfirm
16 | mv ./*.pkg.tar.zst "../$OUTDIR/"
17 | popd > /dev/null
18 | done
19 |
20 | echo -e "${GREEN}✅ All packages built and moved to $OUTDIR${NC}"
21 | notify-send "All packages built" "All packages have been built and moved to $OUTDIR" -a "Sleex packages"
--------------------------------------------------------------------------------
/sleex-packages/sleex-bibata-modern-classic-bin/PKGBUILD:
--------------------------------------------------------------------------------
1 | pkgname=sleex-bibata-modern-classic-bin
2 | pkgver=2.0.6
3 | pkgrel=3
4 | pkgdesc="Material Based Cursor Theme, installed for Sleex"
5 | arch=('any')
6 | url="https://github.com/ful1e5/Bibata_Cursor"
7 | license=('GPL-3.0-or-later')
8 | conflicts=("bibata-cursor-theme" "bibata-cursor-theme-bin")
9 | options=('!strip')
10 | _variant=Bibata-Modern-Classic
11 | source=("${pkgname%-bin}-$pkgver.tar.xz::$url/releases/download/v$pkgver/$_variant.tar.xz")
12 | sha256sums=('SKIP')
13 |
14 | package() {
15 | install -dm755 "$pkgdir/usr/share/icons"
16 | cp -dr --no-preserve=mode $_variant "$pkgdir/usr/share/icons"
17 | }
18 |
--------------------------------------------------------------------------------
/sleex-packages/sleex-microtex-git/.gitignore:
--------------------------------------------------------------------------------
1 | /MicroTeX/
2 |
--------------------------------------------------------------------------------
/sleex-packages/sleex-microtex-git/PKGBUILD:
--------------------------------------------------------------------------------
1 | pkgname=sleex-microtex-git
2 | _pkgname=MicroTeX
3 | pkgver=r494.0e3707f
4 | pkgrel=3
5 | pkgdesc='MicroTeX for Sleex.'
6 | #pkgdesc="A dynamic, cross-platform, and embeddable LaTeX rendering library"
7 | arch=("x86_64")
8 | url="https://github.com/NanoMichael/${_pkgname}"
9 | license=('MIT')
10 | depends=('tinyxml2' 'gtkmm3' 'gtksourceviewmm' 'cairomm')
11 | makedepends=("git" "cmake")
12 | source=("git+${url}.git")
13 | sha256sums=("SKIP")
14 |
15 | pkgver() {
16 | cd $_pkgname
17 | printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
18 | }
19 |
20 | build() {
21 | cd $_pkgname
22 | cmake -B build -S . -DCMAKE_BUILD_TYPE=None
23 | cmake --build build
24 | }
25 |
26 | package() {
27 | cd $_pkgname
28 | install -Dm0755 -t "$pkgdir/opt/$_pkgname/" build/LaTeX
29 | cp -r build/res "$pkgdir/opt/$_pkgname/"
30 | install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname/" LICENSE
31 | }
32 |
--------------------------------------------------------------------------------
/sleex-user-config/.gitignore:
--------------------------------------------------------------------------------
1 | pkg/
2 | *.tar.*
--------------------------------------------------------------------------------
/sleex-user-config/PKGBUILD:
--------------------------------------------------------------------------------
1 | pkgname="sleex-user-config"
2 | pkgver="1.10"
3 | pkgrel="1"
4 | pkgdesc="User configuration for Sleex desktop environment"
5 | arch=("x86_64")
6 | depend=("sleex")
7 |
8 | provides=("axskel-hypr")
9 | replaces=("axskel-hypr")
10 | conflicts=("axskel-hypr")
11 |
12 | package(){
13 | mkdir -p ${pkgdir}/etc/skel/
14 | cp -r ${srcdir}/.config/ ${pkgdir}/etc/skel/
15 | }
16 |
--------------------------------------------------------------------------------
/sleex-user-config/README.md:
--------------------------------------------------------------------------------
1 | # axskel-hypr
2 |
3 | `axskel-hypr` is a custom desktop environment setup, featuring the **Hyprland** window manager and pre-configured settings. This package includes configurations for **Hyprland**, alongside several enhancements for usability, aesthetics, and functionality.
4 |
5 |
6 |
7 | After installation, the package deploys configuration files to `/etc/skel`. Customize these files as needed to tailor your desktop environment.
8 |
9 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/Kvantum/kvantum.kvconfig:
--------------------------------------------------------------------------------
1 | [General]
2 | theme=MaterialAdw
3 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/anyrun/config.ron:
--------------------------------------------------------------------------------
1 | Config(
2 | x: Fraction(0.500000),
3 | y: Absolute(15),
4 | width: Fraction(0.300000),
5 | height: Absolute(0),
6 | hide_icons: false,
7 | ignore_exclusive_zones: false,
8 | layer: Overlay,
9 | hide_plugin_info: true,
10 | close_on_click: true,
11 | show_results_immediately: false,
12 | max_entries: None,
13 | )
14 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/anyrun/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | all: unset;
3 | font-size: 1.3rem;
4 | }
5 |
6 | #window,
7 | #match,
8 | #entry,
9 | #plugin,
10 | #main {
11 | background: transparent;
12 | }
13 |
14 | #match.activatable {
15 | border-radius: 16px;
16 | padding: 0.3rem 0.9rem;
17 | margin-top: 0.01rem;
18 | }
19 | #match.activatable:first-child {
20 | margin-top: 0.7rem;
21 | }
22 | #match.activatable:last-child {
23 | margin-bottom: 0.6rem;
24 | }
25 |
26 | #plugin:hover #match.activatable {
27 | border-radius: 10px;
28 | padding: 0.3rem;
29 | margin-top: 0.01rem;
30 | margin-bottom: 0;
31 | }
32 |
33 | #match:selected,
34 | #match:hover,
35 | #plugin:hover {
36 | background: #2e3131;
37 | }
38 |
39 | #entry {
40 | background: #0b0f10;
41 | border: 1px solid #0b0f10;
42 | border-radius: 16px;
43 | margin: 0.5rem;
44 | padding: 0.3rem 1rem;
45 | }
46 |
47 | list > #plugin {
48 | border-radius: 16px;
49 | margin: 0 0.3rem;
50 | }
51 | list > #plugin:first-child {
52 | margin-top: 0.3rem;
53 | }
54 | list > #plugin:last-child {
55 | margin-bottom: 0.3rem;
56 | }
57 | list > #plugin:hover {
58 | padding: 0.6rem;
59 | }
60 |
61 | box#main {
62 | background: #0b0f10;
63 | box-shadow: inset 0 0 0 1px #0b0f10, 0 0 0 1px #0b0f10;
64 | border-radius: 24px;
65 | padding: 0.3rem;
66 | }
67 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/chrome-flags.conf:
--------------------------------------------------------------------------------
1 | --password-store=gnome-libsecret
2 | --ozone-platform-hint=wayland
3 | --gtk-version=4
4 | --ignore-gpu-blocklist
5 | --enable-features=TouchpadOverscrollHistoryNavigation
6 | --enable-wayland-ime
7 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/code-flags.conf:
--------------------------------------------------------------------------------
1 | --ozone-platform-hint=wayland
2 | --gtk-version=4
3 | --ignore-gpu-blocklist
4 | --enable-features=TouchpadOverscrollHistoryNavigation
5 | --enable-wayland-ime
6 | --password-store=gnome-libsecret
7 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/fish/auto-Hypr.fish:
--------------------------------------------------------------------------------
1 | # Auto start Hyprland on tty1
2 | if test -z "$DISPLAY" ;and test "$XDG_VTNR" -eq 1
3 | mkdir -p ~/.cache
4 | exec Hyprland > ~/.cache/hyprland.log ^&1
5 | end
6 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/fish/config.fish:
--------------------------------------------------------------------------------
1 | function fish_prompt -d "Write out the prompt"
2 | # This shows up as USER@HOST /home/user/ >, with the directory colored
3 | # $USER and $hostname are set by fish, so you can just use them
4 | # instead of using `whoami` and `hostname`
5 | printf '%s@%s %s%s%s > ' $USER $hostname \
6 | (set_color $fish_color_cwd) (prompt_pwd) (set_color normal)
7 | end
8 |
9 | if status is-interactive
10 | # Commands to run in interactive sessions can go here
11 | set fish_greeting
12 |
13 | end
14 |
15 | starship init fish | source
16 | if test -f ~/.local/state/sleex/user/generated/terminal/sequences.txt
17 | cat ~/.local/state/sleex/user/generated/terminal/sequences.txt
18 | end
19 |
20 | alias pamcan pacman
21 | alias ls 'eza --icons'
22 | alias clear "printf '\033[2J\033[3J\033[1;1H'"
23 |
24 |
25 | # function fish_prompt
26 | # set_color cyan; echo (pwd)
27 | # set_color green; echo '> '
28 | # end
29 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/fish/fish_variables:
--------------------------------------------------------------------------------
1 | # This file contains fish universal variable definitions.
2 | # VERSION: 3.0
3 | SETUVAR __fish_initialized:3400
4 | SETUVAR _fisher_jorgebucaran_2F_fisher_files:\x7e/\x2econfig/fish/functions/fisher\x2efish\x1e\x7e/\x2econfig/fish/completions/fisher\x2efish
5 | SETUVAR _fisher_plugins:jorgebucaran/fisher
6 | SETUVAR _fisher_upgraded_to_4_4:\x1d
7 | SETUVAR fish_color_autosuggestion:555\x1ebrblack
8 | SETUVAR fish_color_cancel:\x2dr
9 | SETUVAR fish_color_command:blue
10 | SETUVAR fish_color_comment:red
11 | SETUVAR fish_color_cwd:green
12 | SETUVAR fish_color_cwd_root:red
13 | SETUVAR fish_color_end:green
14 | SETUVAR fish_color_error:brred
15 | SETUVAR fish_color_escape:brcyan
16 | SETUVAR fish_color_history_current:\x2d\x2dbold
17 | SETUVAR fish_color_host:normal
18 | SETUVAR fish_color_host_remote:yellow
19 | SETUVAR fish_color_normal:normal
20 | SETUVAR fish_color_operator:brcyan
21 | SETUVAR fish_color_param:cyan
22 | SETUVAR fish_color_quote:yellow
23 | SETUVAR fish_color_redirection:cyan\x1e\x2d\x2dbold
24 | SETUVAR fish_color_search_match:\x2d\x2dbackground\x3d111
25 | SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack
26 | SETUVAR fish_color_status:red
27 | SETUVAR fish_color_user:brgreen
28 | SETUVAR fish_color_valid_path:\x2d\x2dunderline
29 | SETUVAR fish_key_bindings:fish_default_key_bindings
30 | SETUVAR fish_pager_color_completion:normal
31 | SETUVAR fish_pager_color_description:B3A06D\x1eyellow\x1e\x2di
32 | SETUVAR fish_pager_color_prefix:cyan\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
33 | SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
34 | SETUVAR fish_pager_color_selected_background:\x2dr
35 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/fontconfig/conf.d:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | none
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/foot/foot.ini:
--------------------------------------------------------------------------------
1 | shell=fish
2 | term=xterm-256color
3 |
4 | title=foot
5 |
6 | font=JetBrainsMono Nerd Font:size=11
7 | letter-spacing=0
8 | dpi-aware=no
9 |
10 | pad=25x25
11 |
12 | bold-text-in-bright=no
13 |
14 | [scrollback]
15 | lines=10000
16 |
17 | [cursor]
18 | style=beam
19 | blink=no
20 | beam-thickness=1.5
21 | # underline-thickness=
22 |
23 | [key-bindings]
24 | scrollback-up-page=Page_Up
25 | scrollback-down-page=Page_Down
26 | clipboard-copy=Control+c
27 | clipboard-paste=Control+v
28 | # primary-paste=Shift+Insert
29 | search-start=Control+f
30 | font-increase=Control+plus Control+equal Control+KP_Add
31 | font-decrease=Control+minus Control+KP_Subtract
32 | font-reset=Control+0 Control+KP_0
33 |
34 | [search-bindings]
35 | cancel=Escape
36 | find-prev=Shift+F3
37 | find-next=F3 Control+G
38 | delete-prev-word=Control+BackSpace
39 |
40 | [text-bindings]
41 | \x03=Control+Shift+c
42 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/fuzzel/fuzzel.ini:
--------------------------------------------------------------------------------
1 | include="~/.config/fuzzel/fuzzel_theme.ini"
2 | font=Gabarito
3 | terminal=kitty -1
4 | prompt=">> "
5 | layer=overlay
6 |
7 | [border]
8 | radius=17
9 | width=1
10 |
11 | [dmenu]
12 | exit-immediately-if-empty=yes
13 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/fuzzel/fuzzel_theme.ini:
--------------------------------------------------------------------------------
1 | [colors]
2 | background=161217ff
3 | text=e9e0e8ff
4 | selection=4b454dff
5 | selection-text=cdc3ceff
6 | border=4b454ddd
7 | match=dfb8f6ff
8 | selection-match=dfb8f6ff
9 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/apps.conf:
--------------------------------------------------------------------------------
1 | #!
2 | ##! Apps
3 | bind = Super, Return, exec, # Launch foot (terminal)
4 | bind = Super, C, exec, code --password-store=gnome --enable-features=UseOzonePlatform --ozone-platform=wayland # Launch VSCode (editor)
5 | bind = Super, E, exec, pcmanfm-qt # Launch file manager
6 | bind = Super, W, exec, firefox # launch Firefox
7 | bind = Super, X, exec, kwrite # Launch Text Editor
8 | bind = Super, I, exec, qs -p /usr/share/sleex/settings.qml # Launch Sleex Settings
9 | bind = Ctrl+Super, V, exec, pavucontrol # Launch pavucontrol (volume mixer)
10 | bind = Ctrl+Super+Shift, V, exec, easyeffects # Launch EasyEffects (equalizer & other audio effects)
11 | bind = Ctrl+Shift, Escape, exec, missioncenter # Launch System monitor
12 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/custom/env.conf:
--------------------------------------------------------------------------------
1 | # You can put extra environment variables here
2 | # https://wiki.hyprland.org/Configuring/Environment-variables/
3 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/custom/execs.conf:
--------------------------------------------------------------------------------
1 | # You can make apps auto-start here
2 | # Relevant Hyprland wiki section: https://wiki.hyprland.org/Configuring/Keywords/#executing
3 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/custom/general.conf:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/custom/keybinds.conf:
--------------------------------------------------------------------------------
1 | # You can put your preferred keybinds here
2 | # https://wiki.hyprland.org/Configuring/Binds/
3 |
4 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/custom/rules.conf:
--------------------------------------------------------------------------------
1 | # You can put custom rules here
2 | # Window/layer rules: https://wiki.hyprland.org/Configuring/Window-Rules/
3 | # Workspace rules: https://wiki.hyprland.org/Configuring/Workspace-Rules/
4 |
5 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/custom/scripts/__restore_video_wallpaper.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # The content of this script will be generated by switchwall.sh - Don't modify it by yourself.
3 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/hypridle.conf:
--------------------------------------------------------------------------------
1 | general {
2 | lock_cmd = qs -p /usr/share/sleex ipc call lock lock
3 | before_sleep_cmd = qs -p /usr/share/sleex ipc call lock lock # lock before suspend.
4 | after_sleep_cmd = hyprctl dispatch dpms on # to avoid having to press a key twice to turn on the display.
5 | }
6 |
7 | listener {
8 | timeout = 60 # 1min.
9 | on-timeout = brightnessctl -s set 10 # set monitor backlight to minimum, avoid 0 on OLED monitor.
10 | on-resume = brightnessctl -r # monitor backlight restore.
11 | }
12 |
13 | # turn off keyboard backlight if present (auto-detect device)
14 | listener {
15 | timeout = 180 # 3min.
16 | on-timeout = KBD=$(ls /sys/class/leds | grep -i kbd_backlight | head -n1) && \
17 | [ -n "$KBD" ] && brightnessctl -sd "$KBD" set 0
18 | on-resume = KBD=$(ls /sys/class/leds | grep -i kbd_backlight | head -n1) && \
19 | [ -n "$KBD" ] && brightnessctl -rd "$KBD"
20 | }
21 |
22 | listener {
23 | timeout = 300 # 5min.
24 | on-timeout = qs -p /usr/share/sleex ipc call lock lock # lock screen when timeout has passed
25 | }
26 |
27 | listener {
28 | timeout = 220 # 3min, 40sec
29 | on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed
30 | on-resume = hyprctl dispatch dpms on && brightnessctl -r # screen on when activity is detected after timeout has fired.
31 | }
32 |
33 | listener {
34 | timeout = 600 # 10min
35 | on-timeout = systemctl suspend # suspend pc
36 | }
37 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/hyprland.conf:
--------------------------------------------------------------------------------
1 | # This file sources other files in `hyprland` and `custom` folders
2 | # You wanna add your stuff in file in `custom`
3 | exec = hyprctl dispatch submap global
4 | submap = global
5 | # Defaults
6 | source=~/.config/hypr/hyprland/env.conf
7 | source=~/.config/hypr/hyprland/execs.conf
8 | source=~/.config/hypr/hyprland/general.conf
9 | source=~/.config/hypr/hyprland/rules.conf
10 | source=~/.config/hypr/hyprland/colors.conf
11 | source=~/.config/hypr/hyprland/keybinds.conf
12 |
13 | # Custom
14 | source=~/.config/hypr/custom/env.conf
15 | source=~/.config/hypr/custom/execs.conf
16 | source=~/.config/hypr/custom/general.conf
17 | source=~/.config/hypr/custom/rules.conf
18 | source=~/.config/hypr/custom/keybinds.conf
19 |
20 | source=~/.config/hypr/monitors.conf
21 |
22 | # Applications bindings
23 | source=~/.config/hypr/apps.conf
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/hyprland/colors.conf:
--------------------------------------------------------------------------------
1 | general {
2 | col.active_border = rgba(dfe3e739)
3 | col.inactive_border = rgba(8b919830)
4 | }
5 |
6 | misc {
7 | background_color = rgba(101417FF)
8 | }
9 |
10 | plugin {
11 | hyprbars {
12 | # Honestly idk if it works like css, but well, why not
13 | bar_text_font = Rubik, Geist, AR One Sans, Reddit Sans, Inter, Roboto, Ubuntu, Noto Sans, sans-serif
14 | bar_height = 30
15 | bar_padding = 10
16 | bar_button_padding = 5
17 | bar_precedence_over_border = true
18 | bar_part_of_window = true
19 |
20 | bar_color = rgba(101417FF)
21 | col.text = rgba(dfe3e7FF)
22 |
23 |
24 | # example buttons (R -> L)
25 | # hyprbars-button = color, size, on-click
26 | hyprbars-button = rgb(dfe3e7), 13, , hyprctl dispatch killactive
27 | hyprbars-button = rgb(dfe3e7), 13, , hyprctl dispatch fullscreen 1
28 | hyprbars-button = rgb(dfe3e7), 13, , hyprctl dispatch movetoworkspacesilent special
29 | }
30 | }
31 |
32 | windowrulev2 = bordercolor rgba(93cdf6AA) rgba(93cdf677),pinned:1
33 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/hyprland/env.conf:
--------------------------------------------------------------------------------
1 | # ######### Input method ##########
2 | # See https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland
3 | env = QT_IM_MODULE, fcitx
4 | env = XMODIFIERS, @im=fcitx
5 | # env = GTK_IM_MODULE, wayland # Crashes electron apps in xwayland
6 | env = SDL_IM_MODULE, fcitx
7 | env = GLFW_IM_MODULE, ibus
8 | env = INPUT_METHOD, fcitx
9 |
10 | # ############ Themes #############
11 | env = QT_QPA_PLATFORM, wayland
12 | env = QT_QPA_PLATFORMTHEME, kde
13 | env = QT_STYLE_OVERRIDE,kvantum
14 | # env = WLR_NO_HARDWARE_CURSORS, 1
15 |
16 | env = XDG_SESSION_TYPE, wayland
17 | env = GDK_BACKEND, wayland
18 | env = QT_QPA_PLATFORM, wayland
19 | env = SDL_VIDEODRIVER, wayland
20 | env = CLUTTER_BACKEND, wayland
21 | env = MOZ_ENABLE_WAYLAND, 1
22 |
23 | # ######## Screen tearing #########
24 | # env = WLR_DRM_NO_ATOMIC, 1
25 |
26 | # ############ Others #############
27 |
28 | env = SLEEX_VIRTUAL_ENV, ~/.local/state/sleex/.venv
29 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/hyprland/execs.conf:
--------------------------------------------------------------------------------
1 | # Bar, wallpaper
2 | # exec-once = swww-daemon
3 | exec-once = qs -p /usr/share/sleex &
4 |
5 | # Core components (authentication, lock screen, notification daemon)
6 | exec-once = gnome-keyring-daemon --start --components=secrets
7 | exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 || /usr/libexec/polkit-gnome-authentication-agent-1
8 | exec-once = hypridle
9 | exec-once = dbus-update-activation-environment --all
10 | exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # Some fix idk
11 |
12 | # Audio
13 | exec-once = easyeffects --gapplication-service
14 |
15 | # Clipboard: history
16 | # exec-once = wl-paste --watch cliphist store &
17 | exec-once = wl-paste --type text --watch cliphist store
18 | exec-once = wl-paste --type image --watch cliphist store
19 |
20 | # Cursor
21 | exec-once = hyprctl setcursor Bibata-Modern-Classic 24
22 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/monitors.conf:
--------------------------------------------------------------------------------
1 | # Generated by nwg-displays on 2025-06-09 at 12:05:41. Do not edit manually, use `nwg-displays` instead.
2 |
3 | monitor=,preferred,auto,1
4 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/hypr/workspaces.conf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/sleex-user-config/src/.config/hypr/workspaces.conf
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/kitty/kitty.conf:
--------------------------------------------------------------------------------
1 | # Font
2 | font_family JetBrains Mono Nerd Font
3 | font_size 11.0
4 |
5 | # Cursor
6 | cursor_shape beam
7 | cursor_trail 1
8 |
9 | # Padding (why weird value? consistency with foot)
10 | window_margin_width 21.75
11 |
12 | # No stupid close confirmation
13 | confirm_os_window_close 0
14 |
15 | # Use fish shell
16 | shell fish
17 |
18 | # Copy
19 | map ctrl+c copy_or_interrupt
20 |
21 | # Search
22 | map ctrl+f launch --location=hsplit --allow-remote-control kitty +kitten search.py @active-kitty-window-id
23 | map kitty_mod+f launch --location=hsplit --allow-remote-control kitty +kitten search.py @active-kitty-window-id
24 |
25 | # Scroll & Zoom
26 | map page_up scroll_page_up
27 | map page_down scroll_page_down
28 |
29 | map ctrl+plus change_font_size all +1
30 | map ctrl+equal change_font_size all +1
31 | map ctrl+kp_add change_font_size all +1
32 | map ctrl+minus change_font_size all -1
33 | map ctrl+underscore change_font_size all -1
34 | map ctrl+kp_subtract change_font_size all -1
35 | map ctrl+0 change_font_size all 0
36 | map ctrl+kp_0 change_font_size all 0
37 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/kitty/scroll_mark.py:
--------------------------------------------------------------------------------
1 | from kittens.tui.handler import result_handler
2 | from kitty.boss import Boss
3 |
4 |
5 | def main(args: list[str]) -> None:
6 | pass
7 |
8 |
9 | @result_handler(no_ui=True)
10 | def handle_result(
11 | args: list[str], answer: str, target_window_id: int, boss: Boss
12 | ) -> None:
13 | w = boss.window_id_map.get(target_window_id)
14 | if w is not None:
15 | if len(args) > 1 and args[1] != "prev":
16 | w.scroll_to_mark(prev=False)
17 | else:
18 | w.scroll_to_mark()
19 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/matugen/config.toml:
--------------------------------------------------------------------------------
1 | [config]
2 | version_check = false
3 |
4 | [templates.m3colors]
5 | input_path = '~/.config/matugen/templates/colors.json'
6 | output_path = '~/.local/state/sleex/user/generated/colors.json'
7 |
8 | [templates.hyprland]
9 | input_path = '~/.config/matugen/templates/hyprland/colors.conf'
10 | output_path = '~/.config/hypr/hyprland/colors.conf'
11 |
12 | [templates.hyprlock]
13 | input_path = '~/.config/matugen/templates/hyprland/hyprlock.conf'
14 | output_path = '~/.config/hypr/hyprlock.conf'
15 |
16 | [templates.fuzzel]
17 | input_path = '~/.config/matugen/templates/fuzzel/fuzzel_theme.ini'
18 | output_path = '~/.config/fuzzel/fuzzel_theme.ini'
19 |
20 | [templates.gtk3]
21 | input_path = '~/.config/matugen/templates/gtk/gtk-colors.css'
22 | output_path = '~/.config/gtk-3.0/gtk.css'
23 |
24 | [templates.gtk4]
25 | input_path = '~/.config/matugen/templates/gtk/gtk-colors.css'
26 | output_path = '~/.config/gtk-4.0/gtk.css'
27 |
28 | [templates.kde_colors]
29 | input_path = '~/.config/matugen/templates/kde/color.txt'
30 | output_path = '~/.local/state/sleex/user/generated/color.txt'
31 |
32 | [templates.wallpaper]
33 | input_path = '~/.config/matugen/templates/wallpaper.txt'
34 | output_path = '~/.local/state/sleex/user/generated/wallpaper/path.txt'
35 |
36 | [templates.discord]
37 | input_path = '~/.config/matugen/templates/discord.css'
38 | output_path = '~/.config/vesktop/themes/discord.css'
39 |
40 | [templates.vscode]
41 | input_path = '~/.config/matugen/templates/vscode.json'
42 | output_path = "~/.vscode/extensions/sleex-theme/themes/sleex.json"
43 |
44 | [templates.zed]
45 | input_path = '~/.config/matugen/templates/zed.json'
46 | output_path = "~/.config/zed/themes/sleex.json"
47 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/matugen/templates/fuzzel/fuzzel_theme.ini:
--------------------------------------------------------------------------------
1 | [colors]
2 | background={{colors.background.default.hex_stripped}}ff
3 | text={{colors.on_background.default.hex_stripped}}ff
4 | selection={{colors.surface_variant.default.hex_stripped}}ff
5 | selection-text={{colors.on_surface_variant.default.hex_stripped}}ff
6 | border={{colors.surface_variant.default.hex_stripped}}dd
7 | match={{colors.primary.default.hex_stripped}}ff
8 | selection-match={{colors.primary.default.hex_stripped}}ff
9 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/matugen/templates/gtk/gtk-colors.css:
--------------------------------------------------------------------------------
1 | /*
2 | * GTK Colors
3 | * Generated with Matugen
4 | */
5 |
6 | @define-color accent_color {{colors.primary.default.hex}};
7 | @define-color accent_fg_color {{colors.on_primary.default.hex}};
8 | @define-color accent_bg_color {{colors.primary.default.hex}};
9 | @define-color window_bg_color {{colors.background.default.hex}};
10 | @define-color window_fg_color {{colors.on_background.default.hex}};
11 | @define-color headerbar_bg_color {{colors.surface_dim.default.hex}};
12 | @define-color headerbar_fg_color {{colors.on_surface.default.hex}};
13 | @define-color popover_bg_color {{colors.surface_dim.default.hex}};
14 | @define-color popover_fg_color {{colors.on_surface.default.hex}};
15 | @define-color view_bg_color {{colors.surface.default.hex}};
16 | @define-color view_fg_color {{colors.on_surface.default.hex}};
17 | @define-color card_bg_color {{colors.surface.default.hex}};
18 | @define-color card_fg_color {{colors.on_surface.default.hex}};
19 | @define-color sidebar_bg_color @window_bg_color;
20 | @define-color sidebar_fg_color @window_fg_color;
21 | @define-color sidebar_border_color @window_bg_color;
22 | @define-color sidebar_backdrop_color @window_bg_color;
23 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/matugen/templates/hyprland/colors.conf:
--------------------------------------------------------------------------------
1 | general {
2 | col.active_border = rgba({{colors.on_surface.default.hex_stripped}}39)
3 | col.inactive_border = rgba({{colors.outline.default.hex_stripped}}30)
4 | }
5 |
6 | misc {
7 | background_color = rgba({{colors.surface.dark.hex_stripped}}FF)
8 | }
9 |
10 | plugin {
11 | hyprbars {
12 | # Honestly idk if it works like css, but well, why not
13 | bar_text_font = Rubik, Geist, AR One Sans, Reddit Sans, Inter, Roboto, Ubuntu, Noto Sans, sans-serif
14 | bar_height = 30
15 | bar_padding = 10
16 | bar_button_padding = 5
17 | bar_precedence_over_border = true
18 | bar_part_of_window = true
19 |
20 | bar_color = rgba({{colors.background.default.hex_stripped}}FF)
21 | col.text = rgba({{colors.on_background.default.hex_stripped}}FF)
22 |
23 |
24 | # example buttons (R -> L)
25 | # hyprbars-button = color, size, on-click
26 | hyprbars-button = rgb({{colors.on_background.default.hex_stripped}}), 13, , hyprctl dispatch killactive
27 | hyprbars-button = rgb({{colors.on_background.default.hex_stripped}}), 13, , hyprctl dispatch fullscreen 1
28 | hyprbars-button = rgb({{colors.on_background.default.hex_stripped}}), 13, , hyprctl dispatch movetoworkspacesilent special
29 | }
30 | }
31 |
32 | windowrulev2 = bordercolor rgba({{colors.primary.default.hex_stripped}}AA) rgba({{colors.primary.default.hex_stripped}}77),pinned:1
33 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/matugen/templates/kde/color.txt:
--------------------------------------------------------------------------------
1 | {{colors.source_color.default.hex}}
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/matugen/templates/kde/kde-material-you-colors-wrapper.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
4 |
5 | color=$(tr -d '\n' < "$XDG_STATE_HOME/sleex/user/generated/color.txt")
6 |
7 | current_mode=$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null | tr -d "'")
8 | if [[ "$current_mode" == "prefer-dark" ]]; then
9 | mode_flag="-d"
10 | else
11 | mode_flag="-l"
12 | fi
13 |
14 | # Parse --scheme-variant flag
15 | scheme_variant_str=""
16 | while [[ $# -gt 0 ]]; do
17 | case "$1" in
18 | --scheme-variant)
19 | scheme_variant_str="$2"
20 | shift 2
21 | ;;
22 | *)
23 | shift
24 | ;;
25 | esac
26 | done
27 |
28 | # Map string variant to integer
29 | case "$scheme_variant_str" in
30 | scheme-content) sv_num=0 ;;
31 | scheme-expressive) sv_num=1 ;;
32 | scheme-fidelity) sv_num=2 ;;
33 | scheme-monochrome) sv_num=3 ;;
34 | scheme-neutral) sv_num=4 ;;
35 | scheme-tonal-spot) sv_num=5 ;;
36 | scheme-vibrant) sv_num=6 ;;
37 | scheme-rainbow) sv_num=7 ;;
38 | scheme-fruit-salad) sv_num=8 ;;
39 | "") sv_num=5 ;;
40 | *)
41 | echo "Unknown scheme variant: $scheme_variant_str" >&2
42 | exit 1
43 | ;;
44 | esac
45 |
46 | kde-material-you-colors "$mode_flag" --color "$color" -sv "$sv_num"
47 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/matugen/templates/wallpaper.txt:
--------------------------------------------------------------------------------
1 | {{image}}
2 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/mpv/mpv.conf:
--------------------------------------------------------------------------------
1 | keep-open=yes
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/qt5ct/qt5ct.conf:
--------------------------------------------------------------------------------
1 | [Appearance]
2 | color_scheme_path=/usr/share/qt5ct/colors/darker.conf
3 | custom_palette=true
4 | icon_theme=Papirus
5 | standard_dialogs=default
6 | style=kvantum-dark
7 |
8 | [Fonts]
9 | fixed="JetBrainsMono Nerd Font,11,-1,5,50,0,0,0,0,0,Regular"
10 | general="Rubik,11,-1,5,50,0,0,0,0,0"
11 |
12 | [Interface]
13 | activate_item_on_single_click=1
14 | buttonbox_layout=0
15 | cursor_flash_time=1000
16 | dialog_buttons_have_icons=1
17 | double_click_interval=400
18 | gui_effects=General
19 | keyboard_scheme=2
20 | menus_have_icons=true
21 | show_shortcuts_in_context_menus=true
22 | stylesheets=@Invalid()
23 | toolbutton_style=4
24 | underline_shortcut=1
25 | wheel_scroll_lines=3
26 |
27 | [SettingsWindow]
28 | geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x4\x98\0\0\x3\x99\0\0\0\0\0\0\0\0\0\0\x2\xde\0\0\x3\x1\0\0\0\0\x2\0\0\0\a\x80\0\0\0\0\0\0\0\0\0\0\x4\x98\0\0\x3\x99)
29 |
30 | [Troubleshooting]
31 | force_raster_widgets=1
32 | ignored_applications=@Invalid()
33 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/qt6ct/qt6ct.conf:
--------------------------------------------------------------------------------
1 | [Appearance]
2 | color_scheme_path=/home/end/.config/qt6ct/style-colors.conf
3 | custom_palette=true
4 | icon_theme=Papirus
5 | standard_dialogs=default
6 | style=kvantum
7 |
8 | [Fonts]
9 | fixed="JetBrainsMono Nerd Font,11,-1,5,400,0,0,0,0,0,0,0,0,0,0,1,Regular"
10 | general="Rubik,11,-1,5,400,0,0,0,0,0,0,0,0,0,0,1,Regular"
11 |
12 | [Interface]
13 | activate_item_on_single_click=1
14 | buttonbox_layout=0
15 | cursor_flash_time=1000
16 | dialog_buttons_have_icons=1
17 | double_click_interval=400
18 | gui_effects=@Invalid()
19 | keyboard_scheme=2
20 | menus_have_icons=true
21 | show_shortcuts_in_context_menus=true
22 | stylesheets=@Invalid()
23 | toolbutton_style=4
24 | underline_shortcut=1
25 | wheel_scroll_lines=3
26 |
27 | [SettingsWindow]
28 | geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\as\0\0\x4\x3\0\0\0\0\0\0\0\0\0\0\as\0\0\x4\x3\0\0\0\0\x2\0\0\0\a\x80\0\0\0\0\0\0\0\0\0\0\as\0\0\x4\x3)
29 |
30 | [Troubleshooting]
31 | force_raster_widgets=1
32 | ignored_applications=@Invalid()
33 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/thorium-flags.conf:
--------------------------------------------------------------------------------
1 | --password-store=gnome-libsecret
2 | --ozone-platform-hint=wayland
3 | --gtk-version=4
4 | --ignore-gpu-blocklist
5 | --enable-features=TouchpadOverscrollHistoryNavigation
6 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/wlogout/layout:
--------------------------------------------------------------------------------
1 | {
2 | "label" : "lock",
3 | "action" : "loginctl lock-session",
4 | "text" : "lock",
5 | "keybind" : "l"
6 | }
7 | {
8 | "label" : "hibernate",
9 | "action" : "systemctl hibernate || loginctl hibernate",
10 | "text" : "save",
11 | "keybind" : "h"
12 | }
13 | {
14 | "label" : "logout",
15 | "action" : "pkill Hyprland || pkill sway || pkill niri || loginctl terminate-user $USER",
16 | "text" : "logout",
17 | "keybind" : "e"
18 | }
19 | {
20 | "label" : "shutdown",
21 | "action" : "systemctl poweroff || loginctl poweroff",
22 | "text" : "power_settings_new",
23 | "keybind" : "s"
24 | }
25 | {
26 | "label" : "suspend",
27 | "action" : "systemctl suspend || loginctl suspend",
28 | "text" : "bedtime",
29 | "keybind" : "u"
30 | }
31 | {
32 | "label" : "reboot",
33 | "action" : "systemctl reboot || loginctl reboot",
34 | "text" : "restart_alt",
35 | "keybind" : "r"
36 | }
37 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/wlogout/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | all: unset;
3 | background-image: none;
4 | transition: 400ms cubic-bezier(0.05, 0.7, 0.1, 1);
5 | }
6 |
7 | window {
8 | background: rgba(0, 0, 0, 0.5);
9 | }
10 |
11 | button {
12 | font-family: 'Material Symbols Outlined';
13 | font-size: 10rem;
14 | background-color: rgba(11, 11, 11, 0.4);
15 | color: #FFFFFF;
16 | margin: 2rem;
17 | border-radius: 2rem;
18 | padding: 3rem;
19 | }
20 |
21 | button:focus,
22 | button:active,
23 | button:hover {
24 | background-color: rgba(51, 51, 51, 0.5);
25 | border-radius: 4rem;
26 | }
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/xdg-desktop-portal/hyprland-portals.conf:
--------------------------------------------------------------------------------
1 | [preferred]
2 | default = hyprland;gtk
3 | org.freedesktop.impl.portal.FileChooser = kde
4 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/zshrc.d/auto-Hypr.sh:
--------------------------------------------------------------------------------
1 | # Auto start Hyprland on tty1
2 | if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" -eq 1 ]; then
3 | mkdir -p ~/.cache
4 | exec Hyprland > ~/.cache/hyprland.log 2>&1
5 | fi
6 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/zshrc.d/dots-hyprland.zsh:
--------------------------------------------------------------------------------
1 | # Use the generated color scheme
2 |
3 | if test -f ~/.local/state/sleex/user/generated/terminal/sequences.txt; then
4 | cat ~/.local/state/sleex/user/generated/terminal/sequences.txt
5 | fi
6 |
--------------------------------------------------------------------------------
/sleex-user-config/src/.config/zshrc.d/shortcuts.zsh:
--------------------------------------------------------------------------------
1 | # Created by newuser for 5.9
2 |
3 | bindkey '^H' backward-kill-word
4 | bindkey '^Z' undo
5 |
--------------------------------------------------------------------------------
/src/bin/rubyshot:
--------------------------------------------------------------------------------
1 | #!/usr/bin/bash
2 |
3 | WORKSPACES="$(hyprctl monitors -j | jq -r 'map(.activeWorkspace.id)')"
4 | WINDOWS="$(hyprctl clients -j | jq -r --argjson workspaces "$WORKSPACES" 'map(select([.workspace.id] | inside($workspaces)))' )"
5 | GEOM=$(echo "$WINDOWS" | jq -r '.[] | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | slurp -f '%x %y %w %h')
6 | wayshot -s "$GEOM" --stdout ${#:+"$@"}
--------------------------------------------------------------------------------
/src/bin/sleex:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | export XDG_CURRENT_DESKTOP="Sleex"
3 | export HYPRLAND_INSTANCE_SIGNATURE=""
4 | systemctl --user import-environment XDG_CURRENT_DESKTOP
5 | Hyprland
6 |
--------------------------------------------------------------------------------
/src/share/sleex/.gitignore:
--------------------------------------------------------------------------------
1 | .qmlls.ini
2 | .qt/
3 | .rcc/
4 | .vscode
5 | build/
6 | CMakeFiles/
7 | CMakeCache.txt
8 | cmake_install.cmake
9 | Makefile
10 | qml/
--------------------------------------------------------------------------------
/src/share/sleex/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.19)
2 |
3 | project(sleex VERSION 1.15 LANGUAGES CXX)
4 |
5 | set(CMAKE_CXX_STANDARD 20)
6 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
7 | set(CMAKE_CXX_EXTENSIONS OFF)
8 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
9 | set(CMAKE_INSTALL_PREFIX "/")
10 |
11 | set(DISTRIBUTOR "Unset" CACHE STRING "Distributor")
12 | set(INSTALL_LIBDIR "usr/lib/sleex" CACHE STRING "Library install dir")
13 | set(INSTALL_QMLDIR "usr/lib/qt6/qml" CACHE STRING "QML install dir")
14 |
15 | add_subdirectory(plugins)
16 |
--------------------------------------------------------------------------------
/src/share/sleex/assets/icons/ai-openai-symbolic.svg:
--------------------------------------------------------------------------------
1 | openai-symbolic.svg
--------------------------------------------------------------------------------
/src/share/sleex/assets/icons/cloudflare-dns-symbolic.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/share/sleex/assets/icons/desktop-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/src/share/sleex/assets/icons/google-gemini-symbolic.svg:
--------------------------------------------------------------------------------
1 | spark-symbolic.svg
--------------------------------------------------------------------------------
/src/share/sleex/assets/icons/microsoft-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
55 |
--------------------------------------------------------------------------------
/src/share/sleex/assets/icons/mona-loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/icons/mona-loading.gif
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/1024px/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/1024px/black.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/1024px/dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/1024px/dark.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/1024px/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/1024px/light.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/1024px/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/1024px/white.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/128px/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/128px/black.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/128px/dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/128px/dark.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/128px/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/128px/light.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/128px/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/128px/white.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/256px/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/256px/black.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/256px/dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/256px/dark.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/256px/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/256px/light.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/256px/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/256px/white.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/512px/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/512px/black.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/512px/dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/512px/dark.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/512px/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/512px/light.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/512px/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/512px/white.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/logotype/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/logotype/black.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/logotype/dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/logotype/dark.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/logotype/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/logotype/light.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/logo/logotype/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/logo/logotype/white.png
--------------------------------------------------------------------------------
/src/share/sleex/assets/sounds/battery/01_full.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/sounds/battery/01_full.wav
--------------------------------------------------------------------------------
/src/share/sleex/assets/sounds/battery/02_plug.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/sounds/battery/02_plug.wav
--------------------------------------------------------------------------------
/src/share/sleex/assets/sounds/battery/02_unplug.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/sounds/battery/02_unplug.wav
--------------------------------------------------------------------------------
/src/share/sleex/assets/sounds/battery/04_warn.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/sounds/battery/04_warn.wav
--------------------------------------------------------------------------------
/src/share/sleex/assets/sounds/battery/05_critical.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/assets/sounds/battery/05_critical.wav
--------------------------------------------------------------------------------
/src/share/sleex/modules/background/Quote.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 | import Quickshell
4 | import Quickshell.Wayland
5 | import Quickshell.Io
6 | import qs.services
7 |
8 | // System version watermark display
9 | Item {
10 | id: root
11 | property bool visibleQuote: true
12 | property int marginLeft: 30
13 | property int marginBottom: 30
14 |
15 | // Set explicit size to contain the content
16 | width: quoteContent.implicitWidth
17 | height: quoteContent.implicitHeight
18 |
19 | anchors {
20 | left: parent.left
21 | bottom: parent.bottom
22 | leftMargin: marginLeft
23 | bottomMargin: marginBottom
24 | }
25 |
26 | visible: visibleQuote
27 |
28 | RowLayout {
29 | id: quoteContent
30 | spacing: 16
31 |
32 | anchors {
33 | left: parent.left
34 | bottom: parent.bottom
35 | }
36 |
37 | ColumnLayout {
38 | spacing: 2
39 |
40 | Text {
41 | text: Quotes.quote
42 | color: "#40ffffff"
43 | font.pointSize: 14
44 | font.weight: Font.DemiBold
45 | }
46 |
47 | Text {
48 | text: "- " + Quotes.author
49 | color: "#30ffffff"
50 | font.pointSize: 10
51 | font.weight: Font.Medium
52 | visible: text.length > 0
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/ActiveWindow.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 | import QtQuick.Layouts
5 | import Quickshell.Wayland
6 | import Quickshell.Hyprland
7 |
8 | Item {
9 | id: root
10 | required property var bar
11 | readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen)
12 | readonly property Toplevel activeWindow: ToplevelManager.activeToplevel
13 |
14 | implicitWidth: colLayout.implicitWidth
15 |
16 | ColumnLayout {
17 | id: colLayout
18 |
19 | anchors.verticalCenter: parent.verticalCenter
20 | anchors.left: parent.left
21 | anchors.right: parent.right
22 | spacing: -4
23 |
24 | StyledText {
25 | Layout.fillWidth: true
26 | font.pixelSize: Appearance.font.pixelSize.smaller
27 | color: Appearance.colors.colSubtext
28 | elide: Text.ElideRight
29 | text: root.activeWindow?.activated ? root.activeWindow?.appId : qsTr("Desktop")
30 | }
31 |
32 | StyledText {
33 | Layout.fillWidth: true
34 | font.pixelSize: Appearance.font.pixelSize.small
35 | color: Appearance.colors.colOnLayer0
36 | elide: Text.ElideRight
37 | text: root.activeWindow?.activated ? root.activeWindow?.title : `${qsTr("Workspace")} ${monitor.activeWorkspace?.id}`
38 | }
39 |
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/AudioOsd.qml:
--------------------------------------------------------------------------------
1 | import Quickshell
2 | import Quickshell.Hyprland
3 | import QtQuick.Layouts
4 | import QtQuick
5 | import qs.modules.common
6 | import qs.modules.common.widgets
7 | import qs.services
8 |
9 | Revealer {
10 | id: root
11 | reveal: showOsdValues
12 |
13 | property bool showOsdValues: false
14 |
15 | function triggerOsd() {
16 | showOsdValues = true
17 | osdTimeout.restart()
18 | }
19 |
20 | Connections { // Listen to volume changes
21 | target: Audio.sink?.audio ?? null
22 | function onVolumeChanged() {
23 | if (!Audio.ready) return
24 | root.triggerOsd()
25 | }
26 | function onMutedChanged() {
27 | if (!Audio.ready) return
28 | root.triggerOsd()
29 | }
30 | }
31 |
32 | Connections { // Listen to protection triggers
33 | target: Audio
34 | function onSinkProtectionTriggered(reason) {
35 | root.protectionMessage = reason;
36 | root.triggerOsd()
37 | }
38 | }
39 |
40 | Timer {
41 | id: osdTimeout
42 | interval: Config.options.osd.timeout
43 | repeat: false
44 | running: false
45 | onTriggered: {
46 | showOsdValues = false
47 | }
48 | }
49 |
50 | RowLayout {
51 |
52 | BarGroupR {
53 | id: brightnessOsd
54 | padding: 10
55 |
56 | MaterialSymbol {
57 | text: "volume_up"
58 | iconSize: Appearance.font.pixelSize.normal
59 | }
60 |
61 | Item {
62 | implicitWidth: 5
63 | }
64 |
65 | StyledProgressBar {
66 | value: Audio.sink?.audio.volume ?? 0
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/BarGroupCenter.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 | import QtQuick.Layouts
6 |
7 | Item {
8 | id: root
9 | property real padding: 5
10 | property real margin: 0
11 | implicitHeight: 40
12 | implicitWidth: rowLayout.implicitWidth + padding * 2
13 | default property alias items: rowLayout.children
14 |
15 | Rectangle {
16 | id: background
17 | color: "transparent"
18 | anchors.fill: parent
19 |
20 |
21 | RowLayout {
22 | id: rowLayout
23 | spacing: 0
24 |
25 | anchors {
26 | verticalCenter: parent.verticalCenter
27 | leftMargin: root.margin
28 | rightMargin: root.margin
29 | }
30 |
31 | }
32 |
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/BarGroupL.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 | import QtQuick.Layouts
6 |
7 | Item {
8 | id: root
9 | property real padding: 5
10 | implicitHeight: 40
11 | implicitWidth: rowLayout.implicitWidth + padding * 2
12 | default property alias items: rowLayout.children
13 |
14 | RowLayout {
15 | id: rowLayout
16 | anchors {
17 | verticalCenter: parent.verticalCenter
18 | left: parent.left
19 | right: parent.right
20 | leftMargin: root.padding
21 | rightMargin: root.padding
22 | }
23 | spacing: 4
24 |
25 | }
26 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/BarGroupR.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 | import QtQuick.Layouts
6 |
7 | Item {
8 | id: root
9 | property real padding: 5
10 | implicitHeight: 40
11 | implicitWidth: rowLayout.implicitWidth + padding * 2
12 | default property alias items: rowLayout.children
13 |
14 | RowLayout {
15 | id: rowLayout
16 | anchors {
17 | verticalCenter: parent.verticalCenter
18 | left: parent.left
19 | right: parent.right
20 | leftMargin: root.padding
21 | rightMargin: root.padding
22 | }
23 | spacing: 4
24 |
25 | }
26 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/BrightnessOsd.qml:
--------------------------------------------------------------------------------
1 | import Quickshell
2 | import Quickshell.Hyprland
3 | import QtQuick
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 | import qs.services
7 |
8 | Revealer {
9 | id: root
10 | reveal: showOsdValues
11 |
12 | property bool showOsdValues: false
13 | property var focusedScreen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name)
14 | property var brightnessMonitor: Brightness.getMonitorForScreen(focusedScreen)
15 |
16 | Connections {
17 | target: Brightness
18 | function onBrightnessChanged() {
19 | if (!root.brightnessMonitor.ready) return
20 | root.triggerOsd()
21 | }
22 | }
23 |
24 | function triggerOsd() {
25 | showOsdValues = true
26 | osdTimeout.restart()
27 | }
28 |
29 | Timer {
30 | id: osdTimeout
31 | interval: Config.options.osd.timeout
32 | repeat: false
33 | running: false
34 | onTriggered: {
35 | showOsdValues = false
36 | }
37 | }
38 |
39 | BarGroupR {
40 | id: brightnessOsd
41 | padding: 10
42 |
43 | StyledProgressBar {
44 | value: root.brightnessMonitor?.brightness ?? 0.5
45 | }
46 |
47 | Item {
48 | implicitWidth: 5
49 | }
50 |
51 | MaterialSymbol {
52 | text: "clear_day"
53 | iconSize: Appearance.font.pixelSize.normal
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/BtPopup.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 | import Quickshell.Bluetooth
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 |
7 | Rectangle {
8 | id: resourcePopup
9 | readonly property real margin: 10
10 | implicitWidth: columnLayout.implicitWidth + margin * 2
11 | implicitHeight: columnLayout.implicitHeight + margin * 2
12 | color: Appearance.m3colors.m3background
13 | radius: Appearance.rounding.small
14 | border.width: 1
15 | border.color: Appearance.colors.colLayer0
16 | clip: true
17 |
18 | property BluetoothDevice device: Bluetooth.devices.values.find(d => d.connected) ?? null
19 |
20 | ColumnLayout {
21 | id: columnLayout
22 | anchors.centerIn: parent
23 | spacing: 6
24 |
25 | RowLayout {
26 | spacing: 5
27 |
28 | MaterialSymbol {
29 | fill: 1
30 | text: "bluetooth"
31 | iconSize: Appearance.font.pixelSize.larger
32 | }
33 |
34 | StyledText {
35 | color: Appearance.colors.colOnLayer1
36 | text: device.name
37 | }
38 | }
39 | RowLayout {
40 | spacing: 5
41 |
42 | MaterialSymbol {
43 | fill: 1
44 | text: "battery_android_full"
45 | }
46 |
47 | StyledText {
48 | color: Appearance.colors.colOnLayer1
49 | text: `${Math.round(device.battery * 100 ?? 0)}% remaining`
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/CircleUtilButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 | import Quickshell
8 | import Quickshell.Io
9 |
10 | RippleButton {
11 | id: button
12 |
13 | required default property Item content
14 | property bool extraActiveCondition: false
15 |
16 | implicitHeight: Math.max(content.implicitHeight, 26, content.implicitHeight)
17 | implicitWidth: implicitHeight
18 | contentItem: content
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/HyprlandXkbIndicator.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import qs.services
3 | import qs.modules.common
4 | import qs.modules.common.widgets
5 |
6 | Loader {
7 | id: root
8 | property bool vertical: false
9 | active: HyprlandXkb.layoutCodes.length > 1
10 | visible: active
11 |
12 | function abbreviateLayoutCode(fullCode) {
13 | return fullCode.split(':').map(layout => {
14 | const baseLayout = layout.split('-')[0];
15 | return baseLayout.slice(0, 4);
16 | }).join('\n');
17 | }
18 |
19 | sourceComponent: Item {
20 | implicitWidth: root.vertical ? null : layoutCodeText.implicitWidth
21 | implicitHeight: root.vertical ? layoutCodeText.implicitHeight : null
22 |
23 | StyledText {
24 | id: layoutCodeText
25 | anchors.centerIn: parent
26 | horizontalAlignment: Text.AlignHCenter
27 | text: abbreviateLayoutCode(HyprlandXkb.currentLayoutCode)
28 | font.pixelSize: text.includes("\n") ? Appearance.font.pixelSize.smallie : Appearance.font.pixelSize.small
29 | color: rightSidebarButton.colText
30 | animateChange: true
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/NotifIndicator.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 | import QtQuick.Layouts
6 | import Quickshell
7 | import Quickshell.Io
8 |
9 | Item {
10 | id: root
11 | property int count: Notifications.list.length
12 | height: 20
13 | width: notifRow.width
14 | visible: count > 0
15 |
16 | RowLayout {
17 | id: notifRow
18 | anchors.margins: 2
19 | spacing: 2
20 |
21 | StyledText {
22 | font.pixelSize: 15
23 | text: count > 99 ? "99+" : count.toString()
24 | color: Appearance.colors.colOnLayer0
25 | }
26 |
27 | MaterialSymbol {
28 | id: icon
29 | iconSize: 20
30 | text: "notifications"
31 | color: Appearance.colors.colOnLayer0
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/Resources.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 | import QtQuick.Layouts
6 | import Quickshell
7 | import Quickshell.Io
8 | import Quickshell.Services.Mpris
9 | import Sleex.Services
10 |
11 | Item {
12 | id: root
13 | property bool alwaysShowAllResources: true
14 | implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
15 | implicitHeight: 32
16 |
17 | RowLayout {
18 | id: rowLayout
19 |
20 | spacing: 0
21 | anchors.fill: parent
22 | anchors.leftMargin: 4
23 | anchors.rightMargin: 4
24 |
25 | Resource {
26 | iconName: "memory"
27 | percentage: ResourceMonitor.memoryUsedPercentage
28 | }
29 |
30 | Resource {
31 | iconName: "swap_horiz"
32 | percentage: ResourceMonitor.swapUsedPercentage
33 | }
34 |
35 | Resource {
36 | iconName: "settings_slow_motion"
37 | percentage: ResourceMonitor.cpuUsage
38 | Layout.leftMargin: shown ? 4 : 0
39 | }
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/bar/ScrollHint.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.modules.common
3 | import qs.modules.common.widgets
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 |
8 | Revealer { // Scroll hint
9 | id: root
10 | property string icon
11 | property string side: "left"
12 | property string tooltipText: ""
13 |
14 | MouseArea {
15 | anchors.right: root.side === "left" ? parent.right : undefined
16 | anchors.left: root.side === "right" ? parent.left : undefined
17 | implicitWidth: contentColumnLayout.implicitWidth
18 | implicitHeight: contentColumnLayout.implicitHeight
19 | property bool hovered: false
20 |
21 | hoverEnabled: true
22 | onEntered: hovered = true
23 | onExited: hovered = false
24 | acceptedButtons: Qt.NoButton
25 |
26 | // StyledToolTip {
27 | // extraVisibleCondition: tooltipText.length > 0
28 | // content: tooltipText
29 | // }
30 |
31 | ColumnLayout {
32 | id: contentColumnLayout
33 | anchors.centerIn: parent
34 | spacing: -5
35 | MaterialSymbol {
36 | Layout.leftMargin: 5
37 | Layout.rightMargin: 5
38 | text: "keyboard_arrow_up"
39 | iconSize: 14
40 | color: Appearance.colors.colSubtext
41 | }
42 | MaterialSymbol {
43 | Layout.leftMargin: 5
44 | Layout.rightMargin: 5
45 | text: root.icon
46 | iconSize: 14
47 | color: Appearance.colors.colSubtext
48 | }
49 | MaterialSymbol {
50 | Layout.leftMargin: 5
51 | Layout.rightMargin: 5
52 | text: "keyboard_arrow_down"
53 | iconSize: 14
54 | color: Appearance.colors.colSubtext
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/Persistent.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 | pragma ComponentBehavior: Bound
3 | import QtQuick
4 | import Quickshell
5 | import Quickshell.Io
6 |
7 | Singleton {
8 | id: root
9 | property alias states: persistentStatesJsonAdapter
10 | property string fileDir: Directories.shellConfig
11 | property string fileName: "states.json"
12 | property string filePath: `${root.fileDir}/${root.fileName}`
13 |
14 | Timer {
15 | id: fileReloadTimer
16 | interval: 100
17 | repeat: false
18 | onTriggered: {
19 | persistentStatesFileView.reload()
20 | }
21 | }
22 |
23 | Timer {
24 | id: fileWriteTimer
25 | interval: 100
26 | repeat: false
27 | onTriggered: {
28 | persistentStatesFileView.writeAdapter()
29 | }
30 | }
31 |
32 | FileView {
33 | id: persistentStatesFileView
34 | path: root.filePath
35 |
36 | watchChanges: true
37 | onFileChanged: fileReloadTimer.restart()
38 | onAdapterUpdated: fileWriteTimer.restart()
39 | onLoadFailed: error => {
40 | console.log("Failed to load persistent states file:", error);
41 | if (error == FileViewError.FileNotFound) {
42 | fileWriteTimer.restart();
43 | }
44 | }
45 |
46 | adapter: JsonAdapter {
47 | id: persistentStatesJsonAdapter
48 | property JsonObject ai: JsonObject {
49 | property string model
50 | property real temperature: 0.5
51 | }
52 |
53 | property JsonObject sidebar: JsonObject {
54 | property JsonObject bottomGroup: JsonObject {
55 | property bool collapsed: false
56 | property int tab: 0
57 | }
58 | }
59 |
60 | property JsonObject idle: JsonObject {
61 | property bool inhibit: false
62 | }
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/PersistentStates.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import Quickshell
3 | pragma Singleton
4 | pragma ComponentBehavior: Bound
5 |
6 | Singleton {
7 | property QtObject ai: QtObject {
8 | property string model
9 | property real temperature: 0.5
10 | }
11 |
12 | property QtObject sidebar: QtObject {
13 | property QtObject bottomGroup: QtObject {
14 | property bool collapsed: false
15 | }
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/functions/FileUtils.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 | import Quickshell
3 |
4 | Singleton {
5 | id: root
6 |
7 | /**
8 | * Trims the File protocol off the input string
9 | * @param {string} str
10 | * @returns {string}
11 | */
12 | function trimFileProtocol(str) {
13 | return str.startsWith("file://") ? str.slice(7) : str;
14 | }
15 |
16 | /**
17 | * Extracts the file name from a file path
18 | * @param {string} str
19 | * @returns {string}
20 | */
21 | function fileNameForPath(str) {
22 | if (typeof str !== "string") return "";
23 | const trimmed = trimFileProtocol(str);
24 | return trimmed.split(/[\\/]/).pop();
25 | }
26 |
27 | /**
28 | * Removes the file extension from a file path or name
29 | * @param {string} str
30 | * @returns {string}
31 | */
32 | function trimFileExt(str) {
33 | if (typeof str !== "string") return "";
34 | const trimmed = trimFileProtocol(str);
35 | const lastDot = trimmed.lastIndexOf(".");
36 | if (lastDot > -1 && lastDot > trimmed.lastIndexOf("/")) {
37 | return trimmed.slice(0, lastDot);
38 | }
39 | return trimmed;
40 | }
41 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/functions/Fuzzy.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 | import Quickshell
3 | import "./fuzzysort.js" as FuzzySort
4 |
5 | /**
6 | * Wrapper for FuzzySort to play nicely with Quickshell's imports
7 | */
8 |
9 | Singleton {
10 | function go(...args) {
11 | return FuzzySort.go(...args)
12 | }
13 |
14 | function prepare(...args) {
15 | return FuzzySort.prepare(...args)
16 | }
17 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/functions/Lavendist.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 | import Quickshell
3 | import "./levendist.js" as Levendist
4 |
5 | /**
6 | * Wrapper for levendist.js to play nicely with Quickshell's imports
7 | */
8 |
9 | Singleton {
10 | function computeScore(...args) {
11 | return Levendist.computeScore(...args)
12 | }
13 |
14 | function computeTextMatchScore(...args) {
15 | return Levendist.computeTextMatchScore(...args)
16 | }
17 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ButtonGroup.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 |
8 | /**
9 | * A container that supports GroupButton children for bounciness.
10 | * See https://m3.material.io/components/button-groups/overview
11 | */
12 | Rectangle {
13 | id: root
14 | default property alias data: rowLayout.data
15 | property real spacing: 5
16 | property real padding: 0
17 | property int clickIndex: rowLayout.clickIndex
18 |
19 | property real contentWidth: {
20 | let total = 0;
21 | for (let i = 0; i < rowLayout.children.length; ++i) {
22 | const child = rowLayout.children[i];
23 | total += child.baseWidth ?? child.implicitWidth ?? child.width;
24 | }
25 | return total + rowLayout.spacing * (rowLayout.children.length - 1);
26 | }
27 |
28 | topLeftRadius: rowLayout.children.length > 0 ? (rowLayout.children[0].radius + padding) :
29 | Appearance?.rounding?.small
30 | bottomLeftRadius: topLeftRadius
31 | topRightRadius: rowLayout.children.length > 0 ? (rowLayout.children[rowLayout.children.length - 1].radius + padding) :
32 | Appearance?.rounding?.small
33 | bottomRightRadius: topRightRadius
34 |
35 | color: "transparent"
36 | width: root.contentWidth + padding * 2
37 | implicitHeight: rowLayout.implicitHeight + padding * 2
38 | implicitWidth: root.contentWidth + padding * 2
39 |
40 | children: [RowLayout {
41 | id: rowLayout
42 | anchors.fill: parent
43 | anchors.margins: root.padding
44 | spacing: root.spacing
45 | property int clickIndex: -1
46 | }]
47 | }
48 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/CachingImage.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common.functions
2 | import qs.modules.common
3 | import Quickshell
4 | import Quickshell.Io
5 | import QtQuick
6 |
7 | Image {
8 | id: root
9 |
10 | property string path
11 | property string hash
12 | readonly property string cachePath: `${Directories.wallpaperCache}/${hash}@${effectiveWidth}x${effectiveHeight}.png`
13 |
14 | readonly property real effectiveScale: QsWindow.window?.devicePixelRatio ?? 1
15 | readonly property int effectiveWidth: Math.ceil(width * effectiveScale)
16 | readonly property int effectiveHeight: Math.ceil(height * effectiveScale)
17 |
18 | asynchronous: true
19 | fillMode: Image.PreserveAspectCrop
20 | sourceSize.width: effectiveWidth
21 | sourceSize.height: effectiveHeight
22 |
23 | onPathChanged: shaProc.exec(["sha256sum", FileUtils.trimFileProtocol(path)])
24 |
25 | onCachePathChanged: {
26 | if (hash)
27 | source = cachePath;
28 | }
29 |
30 | onStatusChanged: {
31 | if (source == cachePath && status === Image.Error)
32 | source = path;
33 | else if (source == path && status === Image.Ready) {
34 | Quickshell.execDetached(["mkdir", "-p", FileUtils.trimFileProtocol(cachePath)]);
35 | const grabPath = cachePath;
36 | grabToImage(res => res.saveToFile(grabPath));
37 | }
38 | }
39 |
40 | Process {
41 | id: shaProc
42 |
43 | stdout: StdioCollector {
44 | onStreamFinished: root.hash = text.split(" ")[0]
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ClippingRectangle.qml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/modules/common/widgets/ClippingRectangle.qml
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ConfigRow.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 |
4 | RowLayout {
5 | property bool uniform: false
6 | spacing: 10
7 | uniformCellSizes: uniform
8 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ConfigSelectionArray.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import QtQuick.Layouts
4 | import Quickshell
5 | import Quickshell.Io
6 | import Quickshell.Hyprland
7 | import qs.services
8 | import qs.modules.common
9 | import qs.modules.common.widgets
10 | import qs.modules.common.functions
11 | import qs.modules.common.functions
12 |
13 | Flow {
14 | id: root
15 | Layout.fillWidth: true
16 | spacing: 2
17 | property list options: []
18 | property string configOptionName: ""
19 | property var currentValue: null
20 |
21 | signal selected(var newValue)
22 |
23 | Repeater {
24 | model: root.options
25 | delegate: SelectionGroupButton {
26 | id: paletteButton
27 | required property var modelData
28 | required property int index
29 | onYChanged: {
30 | if (index === 0) {
31 | paletteButton.leftmost = true
32 | } else {
33 | var prev = root.children[index - 1]
34 | var thisIsOnNewLine = prev && prev.y !== paletteButton.y
35 | paletteButton.leftmost = thisIsOnNewLine
36 | prev.rightmost = thisIsOnNewLine
37 | }
38 | }
39 | leftmost: index === 0
40 | rightmost: index === root.options.length - 1
41 | buttonText: modelData.displayName;
42 | toggled: root.currentValue === modelData.value
43 | onClicked: {
44 | root.selected(modelData.value);
45 | }
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ConfigSpinBox.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common.widgets
2 | import qs.modules.common
3 | import QtQuick
4 | import QtQuick.Layouts
5 | import QtQuick.Controls
6 |
7 | RowLayout {
8 | id: root
9 | property string text: ""
10 | property alias value: spinBoxWidget.value
11 | property alias stepSize: spinBoxWidget.stepSize
12 | property alias from: spinBoxWidget.from
13 | property alias to: spinBoxWidget.to
14 | spacing: 10
15 | Layout.leftMargin: 8
16 | Layout.rightMargin: 8
17 |
18 | StyledText {
19 | id: labelWidget
20 | Layout.fillWidth: true
21 | text: root.text
22 | font.pixelSize: Appearance.font.pixelSize.small
23 | color: Appearance.colors.colOnSecondaryContainer
24 | }
25 |
26 | StyledSpinBox {
27 | id: spinBoxWidget
28 | Layout.fillWidth: false
29 | value: root.value
30 | }
31 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ConfigSwitch.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common.widgets
2 | import qs.modules.common
3 | import QtQuick
4 | import QtQuick.Layouts
5 | import QtQuick.Controls
6 |
7 | RippleButton {
8 | id: root
9 | Layout.fillWidth: true
10 | implicitHeight: contentItem.implicitHeight + 8 * 2
11 |
12 | contentItem: RowLayout {
13 | spacing: 10
14 | StyledText {
15 | id: labelWidget
16 | Layout.fillWidth: true
17 | text: root.text
18 | font.pixelSize: Appearance.font.pixelSize.normal
19 | color: Appearance.colors.colOnSecondaryContainer
20 | }
21 | StyledSwitch {
22 | id: switchWidget
23 | down: root.down
24 | scale: 0.75
25 | Layout.fillWidth: false
26 | checked: root.checked
27 | onClicked: root.clicked()
28 | }
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ContentPage.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import QtQuick.Layouts
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 |
7 | StyledFlickable {
8 | id: root
9 | property real baseWidth: 500
10 | property bool forceWidth: false
11 |
12 | default property alias data: contentColumn.data
13 |
14 | clip: true
15 | contentHeight: contentColumn.implicitHeight
16 | implicitWidth: contentColumn.implicitWidth
17 |
18 | ColumnLayout {
19 | id: contentColumn
20 | width: root.forceWidth ? root.baseWidth : Math.max(root.baseWidth, implicitWidth)
21 | anchors {
22 | top: parent.top
23 | bottom: parent.bottom
24 | horizontalCenter: parent.horizontalCenter
25 | margins: 10
26 | }
27 | spacing: 20
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ContentSection.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import QtQuick.Layouts
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 |
7 | ColumnLayout {
8 | id: root
9 | property string title
10 | property color backgroundColor: Appearance.colors.colLayer1
11 | default property alias data: sectionContent.data
12 |
13 | Layout.fillWidth: true
14 | spacing: 8
15 |
16 | StyledText {
17 | text: root.title
18 | font.pixelSize: Appearance.font.pixelSize.larger
19 | font.weight: Font.Medium
20 | }
21 |
22 | Rectangle {
23 | Layout.fillWidth: true
24 | implicitHeight: sectionContent.implicitHeight + 24 // Content height + padding
25 | color: root.backgroundColor
26 | radius: 8 // Optional: rounded corners
27 |
28 | ColumnLayout {
29 | id: sectionContent
30 | anchors.fill: parent
31 | anchors.margins: 12 // Padding inside the background
32 | spacing: 4
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ContentSubsection.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import QtQuick.Layouts
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 |
7 | ColumnLayout {
8 | id: root
9 | property string title: ""
10 | property string tooltip: ""
11 | default property alias data: sectionContent.data
12 |
13 | Layout.fillWidth: true
14 | Layout.topMargin: 4
15 | spacing: 2
16 |
17 | RowLayout {
18 | ContentSubsectionLabel {
19 | visible: root.title && root.title.length > 0
20 | text: root.title
21 | }
22 | MaterialSymbol {
23 | visible: root.tooltip && root.tooltip.length > 0
24 | text: "info"
25 | iconSize: Appearance.font.pixelSize.large
26 |
27 | color: Appearance.colors.colSubtext
28 | MouseArea {
29 | id: infoMouseArea
30 | anchors.fill: parent
31 | hoverEnabled: true
32 | cursorShape: Qt.WhatsThisCursor
33 | StyledToolTip {
34 | extraVisibleCondition: false
35 | alternativeVisibleCondition: infoMouseArea.containsMouse
36 | text: root.tooltip
37 | }
38 | }
39 | }
40 | Item { Layout.fillWidth: true }
41 | }
42 | ColumnLayout {
43 | id: sectionContent
44 | Layout.fillWidth: true
45 | spacing: 2
46 | }
47 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ContentSubsectionLabel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 | import qs.modules.common
4 | import qs.modules.common.widgets
5 |
6 | StyledText {
7 | text: "Subsection"
8 | color: Appearance.colors.colSubtext
9 | Layout.leftMargin: 4
10 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/CustomIcon.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import Quickshell
3 | import Quickshell.Widgets
4 | import Qt5Compat.GraphicalEffects
5 |
6 | Item {
7 | id: root
8 |
9 | property bool colorize: false
10 | property color color
11 | property string source: ""
12 | property string iconFolder: Qt.resolvedUrl(Quickshell.shellPath("assets/icons")) // The folder to check first
13 | width: 30
14 | height: 30
15 |
16 | IconImage {
17 | id: iconImage
18 | anchors.fill: parent
19 | source: {
20 | const fullPathWhenSourceIsIconName = iconFolder + "/" + root.source;
21 | if (iconFolder && fullPathWhenSourceIsIconName) {
22 | return fullPathWhenSourceIsIconName
23 | }
24 | return root.source
25 | }
26 | implicitSize: root.height
27 | }
28 |
29 | Loader {
30 | active: root.colorize
31 | anchors.fill: iconImage
32 | sourceComponent: ColorOverlay {
33 | source: iconImage
34 | color: root.color
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/DialogButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.functions
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 | import Quickshell
7 | import Quickshell.Io
8 |
9 | /**
10 | * Material 3 dialog button. See https://m3.material.io/components/dialogs/overview
11 | */
12 | RippleButton {
13 | id: button
14 |
15 | property string buttonText
16 | implicitHeight: 30
17 | implicitWidth: buttonTextWidget.implicitWidth + 15 * 2
18 | buttonRadius: Appearance?.rounding.full ?? 9999
19 |
20 | property color colEnabled: Appearance?.colors.colPrimary ?? "#65558F"
21 | property color colDisabled: Appearance?.m3colors.m3outline ?? "#8D8C96"
22 |
23 | contentItem: StyledText {
24 | id: buttonTextWidget
25 | anchors.fill: parent
26 | anchors.leftMargin: 15
27 | anchors.rightMargin: 15
28 | text: buttonText
29 | horizontalAlignment: Text.AlignHCenter
30 | font.pixelSize: Appearance?.font.pixelSize.small ?? 12
31 | color: button.enabled ? button.colEnabled : button.colDisabled
32 |
33 | Behavior on color {
34 | animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/Favicon.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import qs.modules.common.functions
5 | import qs.modules.common.functions
6 | import Qt5Compat.GraphicalEffects
7 | import Qt.labs.platform
8 | import QtQuick
9 | import QtQuick.Controls
10 | import QtQuick.Layouts
11 | import Quickshell.Io
12 | import Quickshell.Widgets
13 | import Quickshell.Hyprland
14 |
15 | IconImage {
16 | id: root
17 | property string url
18 | property string displayText
19 |
20 | property real size: 32
21 | property string downloadUserAgent: Config.options?.networking.userAgent ?? ""
22 | property string faviconDownloadPath: Directories.favicons
23 | property string domainName: url.includes("vertexaisearch") ? displayText : StringUtils.getDomain(url)
24 | property string faviconUrl: `https://www.google.com/s2/favicons?domain=${domainName}&sz=32`
25 | property string fileName: `${domainName}.ico`
26 | property string faviconFilePath: `${faviconDownloadPath}/${fileName}`
27 | property string urlToLoad
28 |
29 | Process {
30 | id: faviconDownloadProcess
31 | running: false
32 | command: ["bash", "-c", `[ -f ${faviconFilePath} ] || curl -s '${root.faviconUrl}' -o '${faviconFilePath}' -L -H 'User-Agent: ${downloadUserAgent}'`]
33 | onExited: (exitCode, exitStatus) => {
34 | root.urlToLoad = root.faviconFilePath
35 | }
36 | }
37 |
38 | Component.onCompleted: {
39 | faviconDownloadProcess.running = true
40 | }
41 |
42 | source: Qt.resolvedUrl(root.urlToLoad)
43 | implicitSize: root.size
44 |
45 | layer.enabled: true
46 | layer.effect: OpacityMask {
47 | maskSource: Rectangle {
48 | width: root.implicitSize
49 | height: root.implicitSize
50 | radius: Appearance.rounding.full
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/FlowButtonGroup.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 |
3 | /**
4 | * This is just to make sure `RippleButton`s can be used in a Flow layout.
5 | */
6 | Flow {
7 | property int clickIndex: -1
8 | }
9 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/KeyboardKey.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick
3 | import QtQuick.Controls
4 | import QtQuick.Layouts
5 | import Quickshell
6 | import Quickshell.Io
7 |
8 | Rectangle {
9 | id: root
10 | property string key
11 |
12 | property real horizontalPadding: 7
13 | property real verticalPadding: 2
14 | property real borderWidth: 1
15 | property real extraBottomBorderWidth: 2
16 | property color borderColor: Appearance.colors.colOnLayer0
17 | property real borderRadius: 5
18 | property color keyColor: Appearance.m3colors.m3surfaceContainerLow
19 | implicitWidth: keyFace.implicitWidth + borderWidth * 2
20 | implicitHeight: keyFace.implicitHeight + borderWidth * 2 + extraBottomBorderWidth
21 | radius: borderRadius
22 | color: borderColor
23 |
24 | Rectangle {
25 | id: keyFace
26 | anchors {
27 | fill: parent
28 | topMargin: borderWidth
29 | leftMargin: borderWidth
30 | rightMargin: borderWidth
31 | bottomMargin: extraBottomBorderWidth + borderWidth
32 | }
33 | implicitWidth: keyText.implicitWidth + horizontalPadding * 2
34 | implicitHeight: keyText.implicitHeight + verticalPadding * 2
35 | color: keyColor
36 | radius: borderRadius - borderWidth
37 |
38 | StyledText {
39 | id: keyText
40 | anchors.centerIn: parent
41 | font.family: Appearance.font.family.monospace
42 | font.pixelSize: Appearance.font.pixelSize.smaller
43 | text: key
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/MaterialSymbol.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick
3 | import QtQuick.Layouts
4 |
5 | Text {
6 | id: root
7 | property real iconSize: Appearance?.font.pixelSize.small ?? 16
8 | property real fill: 0
9 | property real truncatedFill: Math.round(fill * 100) / 100 // Reduce memory consumption spikes from constant font remapping
10 | renderType: Text.NativeRendering
11 | font {
12 | hintingPreference: Font.PreferFullHinting
13 | family: Appearance?.font.family.iconMaterial ?? "Material Symbols Rounded"
14 | pixelSize: iconSize
15 | weight: Font.Normal + (Font.DemiBold - Font.Normal) * fill
16 | variableAxes: {
17 | "FILL": truncatedFill,
18 | // "wght": font.weight,
19 | // "GRAD": 0,
20 | "opsz": iconSize,
21 | }
22 | }
23 | verticalAlignment: Text.AlignVCenter
24 | color: Appearance.m3colors.m3onBackground
25 |
26 | // Behavior on fill {
27 | // NumberAnimation {
28 | // duration: Appearance?.animation.elementMoveFast.duration ?? 200
29 | // easing.type: Appearance?.animation.elementMoveFast.type ?? Easing.BezierSpline
30 | // easing.bezierCurve: Appearance?.animation.elementMoveFast.bezierCurve ?? [0.34, 0.80, 0.34, 1.00, 1, 1]
31 | // }
32 | // }
33 | }
34 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/MaterialTextField.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.functions
3 | import QtQuick
4 | import QtQuick.Controls.Material
5 | import QtQuick.Controls
6 |
7 | /**
8 | * Material 3 styled TextArea (filled style)
9 | * https://m3.material.io/components/text-fields/overview
10 | * Note: We don't use NativeRendering because it makes the small placeholder text look weird
11 | */
12 | TextArea {
13 | id: root
14 | Material.theme: Material.System
15 | Material.accent: Appearance.m3colors.m3primary
16 | Material.primary: Appearance.m3colors.m3primary
17 | Material.background: Appearance.m3colors.m3surface
18 | Material.foreground: Appearance.m3colors.m3onSurface
19 | Material.containerStyle: Material.Filled
20 | renderType: Text.QtRendering
21 |
22 | selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
23 | selectionColor: Appearance.colors.colSecondaryContainer
24 | placeholderTextColor: Appearance.m3colors.m3outline
25 |
26 | background: Rectangle {
27 | implicitHeight: 56
28 | color: Appearance.m3colors.m3surface
29 | topLeftRadius: 4
30 | topRightRadius: 4
31 | Rectangle {
32 | anchors {
33 | left: parent.left
34 | right: parent.right
35 | bottom: parent.bottom
36 | }
37 | height: 1
38 | color: root.focus ? Appearance.m3colors.m3primary :
39 | root.hovered ? Appearance.m3colors.m3outline : Appearance.m3colors.m3outlineVariant
40 |
41 | Behavior on color {
42 | animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
43 | }
44 | }
45 | }
46 |
47 | font {
48 | family: Appearance?.font.family.main ?? "sans-serif"
49 | pixelSize: Appearance?.font.pixelSize.small ?? 15
50 | hintingPreference: Font.PreferFullHinting
51 | }
52 | wrapMode: TextEdit.Wrap
53 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/MenuButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.functions
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 | import Quickshell
7 | import Quickshell.Io
8 |
9 | RippleButton {
10 | id: root
11 |
12 | buttonRadius: 0
13 | implicitHeight: 36
14 | implicitWidth: buttonTextWidget.implicitWidth + 14 * 2
15 |
16 | contentItem: StyledText {
17 | id: buttonTextWidget
18 | anchors.fill: parent
19 | anchors.leftMargin: 14
20 | anchors.rightMargin: 14
21 | text: root.buttonText
22 | horizontalAlignment: Text.AlignLeft
23 | font.pixelSize: Appearance.font.pixelSize.small
24 | color: root.enabled ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3outline
25 |
26 | Behavior on color {
27 | animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/NavigationRail.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import QtQuick.Layouts
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 |
7 | ColumnLayout { // Window content with navigation rail and content pane
8 | id: root
9 | property bool expanded: true
10 | property int currentIndex: 0
11 | spacing: 5
12 | }
13 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/NavigationRailExpandButton.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import QtQuick.Layouts
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 |
7 | RippleButton {
8 | id: root
9 | Layout.alignment: Qt.AlignLeft
10 | implicitWidth: 40
11 | implicitHeight: 40
12 | Layout.leftMargin: 8
13 | onClicked: {
14 | parent.expanded = !parent.expanded;
15 | }
16 | buttonRadius: Appearance.rounding.normal
17 | contentItem: MaterialSymbol {
18 | id: icon
19 | anchors.centerIn: parent
20 | horizontalAlignment: Text.AlignHCenter
21 | iconSize: 24
22 | color: Appearance.colors.colOnLayer1
23 | text: root.parent.expanded ? "menu_open" : "menu"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/NavigationRailTabArray.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 | import Quickshell.Io
8 |
9 | Item {
10 | id: root
11 | property int currentIndex: 0
12 | property bool expanded: false
13 | default property alias data: tabBarColumn.data
14 | implicitHeight: tabBarColumn.implicitHeight
15 | implicitWidth: tabBarColumn.implicitWidth
16 | Layout.topMargin: 25
17 | Rectangle {
18 | property real itemHeight: tabBarColumn.children[0].baseSize
19 | property real baseHighlightHeight: tabBarColumn.children[0].baseHighlightHeight
20 | anchors {
21 | top: tabBarColumn.top
22 | left: tabBarColumn.left
23 | topMargin: itemHeight * root.currentIndex + (root.expanded ? 0 : ((itemHeight - baseHighlightHeight) / 2))
24 | }
25 | radius: Appearance.rounding.normal
26 | color: Appearance.colors.colSecondaryContainer
27 | implicitHeight: root.expanded ? itemHeight : baseHighlightHeight
28 | implicitWidth: tabBarColumn.children[root.currentIndex].visualWidth
29 |
30 | Behavior on anchors.topMargin {
31 | NumberAnimation {
32 | duration: Appearance.animationCurves.expressiveFastSpatialDuration
33 | easing.type: Appearance.animation.elementMove.type
34 | easing.bezierCurve: Appearance.animationCurves.expressiveFastSpatial
35 | }
36 | }
37 | }
38 | ColumnLayout {
39 | id: tabBarColumn
40 | anchors.fill: parent
41 | spacing: 0
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/NotificationActionButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.services
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 | import Quickshell
7 | import Quickshell.Services.Notifications
8 |
9 | RippleButton {
10 | id: button
11 | property string buttonText
12 | property string urgency
13 |
14 | implicitHeight: 30
15 | leftPadding: 15
16 | rightPadding: 15
17 | buttonRadius: Appearance.rounding.small
18 | colBackground: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainer : Appearance.colors.colSurfaceContainerHighest
19 | colBackgroundHover: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSurfaceContainerHighestHover
20 | colRipple: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainerActive : Appearance.colors.colSurfaceContainerHighestActive
21 |
22 | contentItem: StyledText {
23 | horizontalAlignment: Text.AlignHCenter
24 | text: buttonText
25 | color: (urgency == NotificationUrgency.Critical) ? Appearance.m3colors.m3onSurfaceVariant : Appearance.m3colors.m3onSurface
26 | }
27 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/NotificationGroupExpandButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.services
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Effects
7 | import QtQuick.Layouts
8 | import Quickshell
9 | import Quickshell.Services.Notifications
10 |
11 | RippleButton { // Expand button
12 | id: root
13 | required property int count
14 | required property bool expanded
15 | property real fontSize: Appearance?.font.pixelSize.small ?? 12
16 | property real iconSize: Appearance?.font.pixelSize.normal ?? 16
17 | implicitHeight: fontSize + 4 * 2
18 | implicitWidth: Math.max(contentItem.implicitWidth + 5 * 2, 30)
19 | Layout.alignment: Qt.AlignVCenter
20 | Layout.fillHeight: false
21 |
22 | buttonRadius: Appearance.rounding.full
23 | colBackground: ColorUtils.mix(Appearance?.colors.colLayer2, Appearance?.colors.colLayer2Hover, 0.5)
24 | colBackgroundHover: Appearance?.colors.colLayer2Hover ?? "#E5DFED"
25 | colRipple: Appearance?.colors.colLayer2Active ?? "#D6CEE2"
26 |
27 | contentItem: Item {
28 | anchors.centerIn: parent
29 | implicitWidth: contentRow.implicitWidth
30 | RowLayout {
31 | id: contentRow
32 | anchors.centerIn: parent
33 | spacing: 3
34 | StyledText {
35 | Layout.leftMargin: 4
36 | visible: root.count > 1
37 | text: root.count
38 | font.pixelSize: root.fontSize
39 | }
40 | MaterialSymbol {
41 | text: "keyboard_arrow_down"
42 | iconSize: root.iconSize
43 | color: Appearance.colors.colOnLayer2
44 | rotation: expanded ? 180 : 0
45 | Behavior on rotation {
46 | animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
47 | }
48 | }
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/NotificationListView.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.modules.common
3 | import qs.modules.common.widgets
4 | import qs.services
5 | import QtQuick
6 | import QtQuick.Controls
7 | import QtQuick.Layouts
8 | import Quickshell
9 | import Quickshell.Wayland
10 | import Quickshell.Hyprland
11 |
12 | StyledListView { // Scrollable window
13 | id: root
14 | property bool popup: false
15 |
16 | spacing: 3
17 |
18 | model: ScriptModel {
19 | values: root.popup ? Notifications.popupAppNameList : Notifications.appNameList
20 | }
21 | delegate: NotificationGroup {
22 | required property int index
23 | required property var modelData
24 | popup: root.popup
25 | anchors.left: parent?.left
26 | anchors.right: parent?.right
27 | notificationGroup: popup ?
28 | Notifications.popupGroupsByAppName[modelData] :
29 | Notifications.groupsByAppName[modelData]
30 | }
31 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/PointingHandInteraction.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 |
3 | MouseArea {
4 | anchors.fill: parent
5 | onPressed: (mouse) => mouse.accepted = false
6 | cursorShape: Qt.PointingHandCursor
7 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/PointingHandLinkHover.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 |
3 | MouseArea {
4 | anchors.fill: parent
5 | acceptedButtons: Qt.NoButton // Only for hover
6 | hoverEnabled: true
7 | cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor
8 | }
9 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/PopupToolTip.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 | import Quickshell
7 |
8 | Item {
9 | id: root
10 | property string text: ""
11 | property bool extraVisibleCondition: true
12 | property bool alternativeVisibleCondition: false
13 | property real horizontalPadding: 10
14 | property real verticalPadding: 5
15 |
16 | property var anchorEdges: Edges.Top
17 | property var anchorGravity: anchorEdges
18 |
19 | readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition
20 |
21 | Loader {
22 | id: tooltipLoader
23 | anchors.fill: parent
24 | active: internalVisibleCondition
25 | sourceComponent: PopupWindow {
26 | visible: true
27 | anchor {
28 | window: root.QsWindow.window
29 | item: root.parent
30 | edges: root.anchorEdges
31 | gravity: root.anchorGravity
32 | }
33 | mask: Region {
34 | item: null
35 | }
36 |
37 | color: "transparent"
38 | implicitWidth: contentItem.implicitWidth + root.horizontalPadding * 2
39 | implicitHeight: contentItem.implicitHeight + root.verticalPadding * 2
40 |
41 | StyledToolTipContent {
42 | id: contentItem
43 | anchors.centerIn: parent
44 | text: root.text
45 | shown: false
46 | Component.onCompleted: shown = true
47 | horizontalPadding: root.horizontalPadding
48 | verticalPadding: root.verticalPadding
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/Revealer.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick
3 | import Quickshell
4 |
5 | /**
6 | * Recreation of GTK revealer. Expects one single child.
7 | */
8 | Item {
9 | id: root
10 | property bool reveal
11 | property bool vertical: false
12 | clip: true
13 |
14 | implicitWidth: (reveal || vertical) ? childrenRect.width : 0
15 | implicitHeight: (reveal || !vertical) ? childrenRect.height : 0
16 | visible: reveal || (width > 0 && height > 0)
17 |
18 | Behavior on implicitWidth {
19 | enabled: !vertical
20 | animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
21 | }
22 | Behavior on implicitHeight {
23 | enabled: vertical
24 | animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/RoundCorner.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.9
2 |
3 | Item {
4 | id: root
5 |
6 | property int size: 25
7 | property color color
8 |
9 | onColorChanged: {
10 | canvas.requestPaint();
11 | }
12 |
13 | property QtObject cornerEnum: QtObject {
14 | property int topLeft: 0
15 | property int topRight: 1
16 | property int bottomLeft: 2
17 | property int bottomRight: 3
18 | }
19 |
20 | property int corner: cornerEnum.topLeft // Default to TopLeft
21 |
22 | width: size
23 | height: size
24 |
25 | Canvas {
26 | id: canvas
27 |
28 | anchors.fill: parent
29 | antialiasing: true
30 |
31 | onPaint: {
32 | var ctx = getContext("2d");
33 | var r = root.size;
34 |
35 | ctx.beginPath();
36 | switch (root.corner) {
37 | case cornerEnum.topLeft:
38 | ctx.arc(r, r, r, Math.PI, 3 * Math.PI / 2);
39 | ctx.lineTo(0, 0);
40 | break;
41 | case cornerEnum.topRight:
42 | ctx.arc(0, r, r, 3 * Math.PI / 2, 2 * Math.PI);
43 | ctx.lineTo(r, 0);
44 | break;
45 | case cornerEnum.bottomLeft:
46 | ctx.arc(r, 0, r, Math.PI / 2, Math.PI);
47 | ctx.lineTo(0, r);
48 | break;
49 | case cornerEnum.bottomRight:
50 | ctx.arc(0, 0, r, 0, Math.PI / 2);
51 | ctx.lineTo(r, r);
52 | break;
53 | }
54 | ctx.closePath();
55 | ctx.fillStyle = root.color;
56 | ctx.fill();
57 | }
58 | }
59 |
60 | Behavior on size {
61 | animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/ScrollEdgeFade.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import qs.modules.common
3 | import qs.modules.common.functions
4 |
5 | Item {
6 | id: root
7 | z: 99
8 | required property Item target
9 | property real fadeSize: Appearance.m3colors.darkmode ? 40 : 20
10 | property color color: ColorUtils.transparentize(Appearance.colors.colShadow, Appearance.m3colors.darkmode ? 0 : 0.7)
11 | property bool vertical: true
12 |
13 | anchors.fill: target
14 |
15 | EndGradient {
16 | anchors {
17 | top: parent.top
18 | left: parent.left
19 | right: vertical ? parent.right : undefined
20 | bottom: vertical ? undefined : parent.bottom
21 | }
22 | shown: !(root.vertical ? root.target.atYBeginning : root.target.atXBeginning)
23 | }
24 |
25 | EndGradient {
26 | anchors {
27 | bottom: parent.bottom
28 | right: parent.right
29 | left: vertical ? parent.left : undefined
30 | top: vertical ? undefined : parent.top
31 | }
32 | shown: !(root.vertical ? root.target.atYEnd : root.target.atXEnd)
33 | rotation: 180
34 | }
35 |
36 | component EndGradient: Rectangle {
37 | required property bool shown
38 | height: vertical ? root.fadeSize : parent.height
39 | width: vertical ? parent.width : root.fadeSize
40 |
41 | opacity: shown ? 1 : 0
42 | visible: opacity > 0
43 | Behavior on opacity {
44 | animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
45 | }
46 |
47 | gradient: Gradient {
48 | orientation: root.vertical ? Gradient.Vertical : Gradient.Horizontal
49 | GradientStop {
50 | position: 0.0
51 | color: root.color
52 | }
53 | GradientStop {
54 | position: 1.0
55 | color: ColorUtils.transparentize(root.color)
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/SelectionGroupButton.qml:
--------------------------------------------------------------------------------
1 | import QtQuick.Controls
2 | import QtQuick.Layouts
3 | import Quickshell
4 | import Quickshell.Io
5 | import Quickshell.Hyprland
6 | import qs.services
7 | import qs.modules.common
8 | import qs.modules.common.widgets
9 |
10 | GroupButton {
11 | id: root
12 | horizontalPadding: 12
13 | verticalPadding: 8
14 | bounce: false
15 | property bool leftmost: false
16 | property bool rightmost: false
17 | leftRadius: (leftmost) ? (height / 2) : Appearance.rounding.unsharpenmore
18 | rightRadius: (rightmost) ? (height / 2) : Appearance.rounding.unsharpenmore
19 | colBackground: Appearance.colors.colSecondaryContainer
20 | contentItem: StyledText {
21 | color: parent.toggled ? Appearance.colors.colOnPrimary : Appearance.colors.colOnSecondaryContainer
22 | text: root.buttonText
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/StyledLabel.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick
3 | import QtQuick.Controls
4 | import QtQuick.Layouts
5 |
6 | Label {
7 | renderType: Text.NativeRendering
8 | verticalAlignment: Text.AlignVCenter
9 | font {
10 | hintingPreference: Font.PreferFullHinting
11 | family: Appearance?.font.family.main ?? "sans-serif"
12 | pixelSize: Appearance?.font.pixelSize.small ?? 15
13 | }
14 | color: Appearance?.m3colors.m3onBackground ?? "black"
15 | linkColor: Appearance?.m3colors.m3primary
16 | }
17 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/StyledRectangularShadow.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Effects
3 | import qs.modules.common
4 |
5 | RectangularShadow {
6 | required property var target
7 | anchors.fill: target
8 | radius: target.radius
9 | blur: 0.9 * Appearance.sizes.elevationMargin
10 | offset: Qt.vector2d(0.0, 1.0)
11 | spread: 1
12 | color: Appearance.colors.colShadow
13 | cached: true
14 | }
15 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/StyledScrollBar.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import qs.modules.common
4 | import qs.modules.common.functions
5 |
6 | ScrollBar {
7 | id: root
8 |
9 | policy: ScrollBar.AsNeeded
10 | topPadding: Appearance.rounding.normal
11 | bottomPadding: Appearance.rounding.normal
12 |
13 | contentItem: Rectangle {
14 | implicitWidth: 4
15 | implicitHeight: root.visualSize
16 | radius: width / 2
17 | color: Appearance.colors.colOutlineVariant
18 |
19 | opacity: root.policy === ScrollBar.AlwaysOn || (root.active && root.size < 1.0) ? 0.5 : 0
20 | Behavior on opacity {
21 | NumberAnimation {
22 | duration: 350
23 | easing.type: Appearance.animation.elementMoveFast.type
24 | easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/StyledTextArea.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick
3 | import QtQuick.Controls
4 |
5 | /**
6 | * Does not include visual layout, but includes the easily neglected colors.
7 | */
8 | TextArea {
9 | renderType: Text.NativeRendering
10 | selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
11 | selectionColor: Appearance.colors.colSecondaryContainer
12 | placeholderTextColor: Appearance.m3colors.m3outline
13 | font {
14 | family: Appearance?.font.family.main ?? "sans-serif"
15 | pixelSize: Appearance?.font.pixelSize.small ?? 15
16 | hintingPreference: Font.PreferFullHinting
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/StyledTextInput.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick
3 | import QtQuick.Controls
4 |
5 | /**
6 | * Does not include visual layout, but includes the easily neglected colors.
7 | */
8 | TextInput {
9 | renderType: Text.NativeRendering
10 | selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
11 | selectionColor: Appearance.colors.colSecondaryContainer
12 | font {
13 | family: Appearance?.font.family.main ?? "sans-serif"
14 | pixelSize: Appearance?.font.pixelSize.small ?? 15
15 | hintingPreference: Font.PreferFullHinting
16 | }
17 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/StyledToolTip.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 |
7 | ToolTip {
8 | id: root
9 | property bool extraVisibleCondition: true
10 | property bool alternativeVisibleCondition: false
11 | readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition
12 | verticalPadding: 5
13 | horizontalPadding: 10
14 | background: null
15 |
16 | visible: internalVisibleCondition
17 |
18 | contentItem: StyledToolTipContent {
19 | id: contentItem
20 | text: root.text
21 | shown: root.internalVisibleCondition
22 | horizontalPadding: root.horizontalPadding
23 | verticalPadding: root.verticalPadding
24 | }
25 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/StyledToolTipContent.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 |
7 | Item {
8 | id: root
9 | required property string text
10 | property bool shown: false
11 | property real horizontalPadding: 10
12 | property real verticalPadding: 5
13 | implicitWidth: tooltipTextObject.implicitWidth + 2 * root.horizontalPadding
14 | implicitHeight: tooltipTextObject.implicitHeight + 2 * root.verticalPadding
15 |
16 | property bool isVisible: backgroundRectangle.implicitHeight > 0
17 |
18 | Rectangle {
19 | id: backgroundRectangle
20 | anchors {
21 | bottom: root.bottom
22 | horizontalCenter: root.horizontalCenter
23 | }
24 | color: Appearance?.colors.colTooltip ?? "#3C4043"
25 | radius: Appearance?.rounding.verysmall ?? 7
26 | opacity: shown ? 1 : 0
27 | implicitWidth: shown ? (tooltipTextObject.implicitWidth + 2 * root.horizontalPadding) : 0
28 | implicitHeight: shown ? (tooltipTextObject.implicitHeight + 2 * root.verticalPadding) : 0
29 | clip: true
30 |
31 | Behavior on implicitWidth {
32 | animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
33 | }
34 | Behavior on implicitHeight {
35 | animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
36 | }
37 | Behavior on opacity {
38 | animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
39 | }
40 |
41 | StyledText {
42 | id: tooltipTextObject
43 | anchors.centerIn: parent
44 | text: root.text
45 | font.pixelSize: Appearance?.font.pixelSize.smaller ?? 14
46 | font.hintingPreference: Font.PreferNoHinting // Prevent shaky text
47 | color: Appearance?.colors.colOnTooltip ?? "#FFFFFF"
48 | wrapMode: Text.Wrap
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/common/widgets/VerticalButtonGroup.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 |
8 | /**
9 | * A container that supports GroupButton children for bounciness.
10 | * See https://m3.material.io/components/button-groups/overview
11 | */
12 | Rectangle {
13 | id: root
14 | default property alias content: columnLayout.data
15 | property real spacing: 5
16 | property real padding: 0
17 | property int clickIndex: columnLayout.clickIndex
18 |
19 | property real contentHeight: {
20 | let total = 0;
21 | for (let i = 0; i < columnLayout.children.length; ++i) {
22 | const child = columnLayout.children[i];
23 | total += child.baseHeight ?? child.implicitHeight ?? child.height;
24 | }
25 | return total + columnLayout.spacing * (columnLayout.children.length - 1);
26 | }
27 |
28 | topLeftRadius: columnLayout.children.length > 0 ? (columnLayout.children[0].radius + padding) :
29 | Appearance?.rounding?.small
30 | topRightRadius: topLeftRadius
31 | bottomLeftRadius: columnLayout.children.length > 0 ? (columnLayout.children[columnLayout.children.length - 1].radius + padding) :
32 | Appearance?.rounding?.small
33 | bottomRightRadius: bottomLeftRadius
34 |
35 | color: "transparent"
36 | height: root.contentHeight + padding * 2
37 | implicitWidth: columnLayout.implicitWidth + padding * 2
38 | implicitHeight: root.contentHeight + padding * 2
39 |
40 | children: [ColumnLayout {
41 | id: columnLayout
42 | anchors.fill: parent
43 | anchors.margins: root.padding
44 | spacing: root.spacing
45 | property int clickIndex: -1
46 | }]
47 | }
48 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/AiWidgetGroup.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import "./ai"
5 | import QtQuick
6 | import QtQuick.Controls
7 | import QtQuick.Layouts
8 | import Quickshell
9 |
10 | Rectangle {
11 | id: root
12 | color: "transparent"
13 | clip: true
14 |
15 | AiChat {
16 | anchors.fill: parent
17 | }
18 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/TodoWidgetGroup.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import "./calendar"
5 | import "./todo"
6 | import QtQuick
7 | import QtQuick.Controls
8 | import QtQuick.Layouts
9 | import Quickshell
10 |
11 | Rectangle {
12 | id: root
13 | color: "transparent"
14 | clip: true
15 |
16 |
17 | TodoWidget {
18 | anchors.fill: parent
19 | anchors.margins: 5
20 | }
21 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/ai/ApiCommandButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 |
5 | GroupButton {
6 | id: button
7 | property string buttonText
8 |
9 | horizontalPadding: 8
10 | verticalPadding: 6
11 |
12 | baseWidth: contentItem.implicitWidth + horizontalPadding * 2
13 | clickedWidth: baseWidth + 20
14 | baseHeight: contentItem.implicitHeight + verticalPadding * 2
15 | buttonRadius: down ? Appearance.rounding.verysmall : Appearance.rounding.small
16 |
17 | colBackground: Appearance.colors.colLayer2
18 | colBackgroundHover: Appearance.colors.colLayer2Hover
19 | colBackgroundActive: Appearance.colors.colLayer2Active
20 |
21 | contentItem: StyledText {
22 | horizontalAlignment: Text.AlignHCenter
23 | text: buttonText
24 | color: Appearance.m3colors.m3onSurface
25 | }
26 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/ai/ApiInputBoxIndicator.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 | import QtQuick.Layouts
6 |
7 | Item { // Model indicator
8 | id: root
9 | property string icon: "api"
10 | property string text: ""
11 | property string tooltipText: ""
12 | implicitHeight: rowLayout.implicitHeight + 4 * 2
13 | implicitWidth: rowLayout.implicitWidth + 4 * 2
14 |
15 | RowLayout {
16 | id: rowLayout
17 | anchors.centerIn: parent
18 |
19 | MaterialSymbol {
20 | text: root.icon
21 | iconSize: Appearance.font.pixelSize.normal
22 | }
23 | StyledText {
24 | id: providerName
25 | font.pixelSize: Appearance.font.pixelSize.smaller
26 | color: Appearance.m3colors.m3onSurface
27 | elide: Text.ElideRight
28 | text: root.text
29 | animateChange: true
30 | }
31 | }
32 |
33 | Loader {
34 | active: root.tooltipText?.length > 0
35 | anchors.fill: parent
36 | sourceComponent: MouseArea {
37 | id: mouseArea
38 | hoverEnabled: true
39 |
40 | StyledToolTip {
41 | id: toolTip
42 | extraVisibleCondition: false
43 | alternativeVisibleCondition: mouseArea.containsMouse // Show tooltip when hovered
44 | text: root.tooltipText
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/ai/DescriptionBox.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.services
3 | import qs.modules.common
4 | import qs.modules.common.widgets
5 | import QtQuick
6 | import QtQuick.Layouts
7 |
8 | Item { // Tag suggestion description
9 | id: root
10 | property alias text: tagDescriptionText.text
11 | property bool showArrows: true
12 | property bool showTab: true
13 |
14 | visible: tagDescriptionText.text.length > 0
15 | Layout.fillWidth: true
16 | implicitHeight: tagDescriptionBackground.implicitHeight
17 |
18 | Rectangle {
19 | id: tagDescriptionBackground
20 | color: Appearance.colors.colLayer2
21 | anchors.fill: parent
22 | radius: Appearance.rounding.verysmall
23 | implicitHeight: descriptionRow.implicitHeight + 5 * 2
24 |
25 | RowLayout {
26 | id: descriptionRow
27 | spacing: 4
28 | anchors {
29 | fill: parent
30 | leftMargin: 10
31 | rightMargin: 10
32 | }
33 |
34 | StyledText {
35 | id: tagDescriptionText
36 | Layout.fillWidth: true
37 | font.pixelSize: Appearance.font.pixelSize.smaller
38 | color: Appearance.colors.colOnLayer2
39 | wrapMode: Text.Wrap
40 | }
41 | KeyboardKey {
42 | visible: root.showArrows
43 | key: "↑"
44 | }
45 | KeyboardKey {
46 | visible: root.showArrows
47 | key: "↓"
48 | }
49 | StyledText {
50 | visible: root.showArrows && root.showTab
51 | text: "or"
52 | font.pixelSize: Appearance.font.pixelSize.smaller
53 | }
54 | KeyboardKey {
55 | id: tagDescriptionKey
56 | visible: root.showTab
57 | key: "Tab"
58 | Layout.alignment: Qt.AlignVCenter
59 | }
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/ai/aiChat/AiMessageControlButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 |
6 | GroupButton {
7 | id: button
8 | property string buttonIcon
9 | property bool activated: false
10 | toggled: activated
11 |
12 | baseWidth: height
13 |
14 | contentItem: MaterialSymbol {
15 | horizontalAlignment: Text.AlignHCenter
16 | iconSize: Appearance.font.pixelSize.larger
17 | text: buttonIcon
18 | color: button.activated ? Appearance.m3colors.m3onPrimary :
19 | button.enabled ? Appearance.m3colors.m3onSurface :
20 | Appearance.colors.colOnLayer1Inactive
21 |
22 | Behavior on color {
23 | animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/ai/aiChat/AnnotationSourceButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import qs.services
5 | import QtQuick
6 | import QtQuick.Layouts
7 | import Quickshell.Hyprland
8 |
9 | RippleButton {
10 | id: root
11 | property string displayText
12 | property string url
13 |
14 | property real faviconSize: 20
15 | implicitHeight: 30
16 | leftPadding: (implicitHeight - faviconSize) / 2
17 | rightPadding: 10
18 | buttonRadius: Appearance.rounding.full
19 | colBackground: Appearance.colors.colSurfaceContainerHighest
20 | colBackgroundHover: Appearance.colors.colSurfaceContainerHighestHover
21 | colRipple: Appearance.colors.colSurfaceContainerHighestActive
22 |
23 | PointingHandInteraction {}
24 | onClicked: {
25 | if (url) {
26 | Qt.openUrlExternally(url)
27 | GlobalStates.sidebarLeftOpen = false
28 | }
29 | }
30 |
31 | contentItem: Item {
32 | anchors.centerIn: parent
33 | implicitWidth: rowLayout.implicitWidth
34 | implicitHeight: rowLayout.implicitHeight
35 | RowLayout {
36 | id: rowLayout
37 | anchors.fill: parent
38 | spacing: 5
39 | Favicon {
40 | url: root.url
41 | size: root.faviconSize
42 | displayText: root.displayText
43 | }
44 | StyledText {
45 | id: text
46 | horizontalAlignment: Text.AlignHCenter
47 | text: displayText
48 | color: Appearance.m3colors.m3onSurface
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/ai/aiChat/SearchQueryButton.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.modules.common
3 | import qs.modules.common.widgets
4 | import qs.services
5 | import qs.modules.common.functions
6 | import QtQuick
7 | import QtQuick.Layouts
8 | import Quickshell.Hyprland
9 |
10 | RippleButton {
11 | id: root
12 | property string query
13 |
14 | implicitHeight: 30
15 | leftPadding: 6
16 | rightPadding: 10
17 | buttonRadius: Appearance.rounding.verysmall
18 | colBackground: Appearance.colors.colSurfaceContainerHighest
19 | colBackgroundHover: Appearance.colors.colSurfaceContainerHighestHover
20 | colRipple: Appearance.colors.colSurfaceContainerHighestActive
21 |
22 | PointingHandInteraction {}
23 | onClicked: {
24 | let url = Config.options.search.engineBaseUrl + root.query;
25 | for (let site of (Config?.options?.search.excludedSites ?? [])) {
26 | url += ` -site:${site}`;
27 | }
28 | Qt.openUrlExternally(url);
29 | GlobalStates.sidebarLeftOpen = false;
30 | }
31 |
32 | contentItem: Item {
33 | anchors.centerIn: parent
34 | implicitWidth: rowLayout.implicitWidth
35 | implicitHeight: rowLayout.implicitHeight
36 | RowLayout {
37 | id: rowLayout
38 | anchors.centerIn: parent
39 | spacing: 5
40 | MaterialSymbol {
41 | text: "search"
42 | iconSize: 20
43 | color: Appearance.m3colors.m3onSurface
44 | }
45 | StyledText {
46 | id: text
47 | horizontalAlignment: Text.AlignHCenter
48 | text: root.query
49 | color: Appearance.m3colors.m3onSurface
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/calendar/CalendarDayButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 |
8 | RippleButton {
9 | id: button
10 | property string day
11 | property int isToday
12 | property bool bold
13 |
14 | Layout.fillWidth: false
15 | Layout.fillHeight: false
16 | implicitWidth: 38;
17 | implicitHeight: 38;
18 |
19 | toggled: (isToday == 1)
20 | buttonRadius: Appearance.rounding.small
21 |
22 | contentItem: StyledText {
23 | anchors.fill: parent
24 | text: day
25 | horizontalAlignment: Text.AlignHCenter
26 | font.weight: bold ? Font.DemiBold : Font.Normal
27 | color: (isToday == 1) ? Appearance.m3colors.m3onPrimary :
28 | (isToday == 0) ? Appearance.colors.colOnLayer1 :
29 | Appearance.colors.colOutlineVariant
30 |
31 | Behavior on color {
32 | animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
33 | }
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/calendar/CalendarHeaderButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 |
7 | RippleButton {
8 | id: button
9 | property string buttonText: ""
10 | property string tooltipText: ""
11 | property bool forceCircle: false
12 |
13 | implicitHeight: 30
14 | implicitWidth: forceCircle ? implicitHeight : (contentItem.implicitWidth + 10 * 2)
15 | Behavior on implicitWidth {
16 | SmoothedAnimation {
17 | velocity: Appearance.animation.elementMove.velocity
18 | }
19 | }
20 |
21 | background.anchors.fill: button
22 | buttonRadius: Appearance.rounding.full
23 | colBackground: Appearance.colors.colLayer2
24 | colBackgroundHover: Appearance.colors.colLayer2Hover
25 | colRipple: Appearance.colors.colLayer2Active
26 |
27 | contentItem: StyledText {
28 | text: buttonText
29 | horizontalAlignment: Text.AlignHCenter
30 | font.pixelSize: Appearance.font.pixelSize.larger
31 | color: Appearance.colors.colOnLayer1
32 | }
33 |
34 | StyledToolTip {
35 | text: tooltipText
36 | extraVisibleCondition: tooltipText.length > 0
37 | }
38 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/notifications/NotificationStatusButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 |
7 | GroupButton {
8 | id: button
9 | property string buttonText: ""
10 | property string buttonIcon: ""
11 |
12 | baseWidth: content.implicitWidth + 10 * 2
13 | baseHeight: 30
14 |
15 | buttonRadius: baseHeight / 2
16 | buttonRadiusPressed: Appearance.rounding.small
17 | colBackground: Appearance.colors.colLayer2
18 | colBackgroundHover: Appearance.colors.colLayer2Hover
19 | colBackgroundActive: Appearance.colors.colLayer2Active
20 | property color colText: toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1
21 |
22 | contentItem: Item {
23 | id: content
24 | anchors.fill: parent
25 | implicitWidth: contentRowLayout.implicitWidth
26 | implicitHeight: contentRowLayout.implicitHeight
27 | RowLayout {
28 | id: contentRowLayout
29 | anchors.centerIn: parent
30 | spacing: 5
31 | MaterialSymbol {
32 | text: buttonIcon
33 | iconSize: Appearance.font.pixelSize.large
34 | color: button.colText
35 | }
36 | StyledText {
37 | text: buttonText
38 | font.pixelSize: Appearance.font.pixelSize.small
39 | color: button.colText
40 | }
41 | }
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/quickToggles/BluetoothToggle.qml:
--------------------------------------------------------------------------------
1 | import "../"
2 | import qs
3 | import qs.services
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 | import qs.modules.common.functions
7 | import QtQuick
8 | import Quickshell
9 | import Quickshell.Io
10 | import Quickshell.Bluetooth
11 | import Quickshell.Hyprland
12 |
13 | import Sleex.Services
14 |
15 | QuickToggleButton {
16 | toggled: Bluetooth.defaultAdapter.enabled
17 | buttonIcon: BluetoothService.bluetoothConnected ? "bluetooth_connected" : Bluetooth.defaultAdapter.enabled ? "bluetooth" : "bluetooth_disabled"
18 | onClicked: {
19 | Bluetooth.defaultAdapter.enabled = !Bluetooth.defaultAdapter.enabled
20 | }
21 | altAction: () => {
22 | Quickshell.execDetached(["bash", "-c", `${Config.options.apps.bluetooth}`])
23 | GlobalStates.dashboardOpen = false
24 | }
25 | Process {
26 | id: toggleBluetooth
27 | command: ["bash", "-c", `bluetoothctl power ${Bluetooth.defaultAdapter.enabled ? "off" : "on"}`]
28 | onRunningChanged: {
29 | if(!running) {
30 | BluetoothService.update()
31 | }
32 | }
33 | }
34 | StyledToolTip {
35 | text: StringUtils.format(qsTr("{0} | Right-click to configure"),
36 | (Bluetooth.defaultAdapter.enabled && BluetoothService.bluetoothDeviceName.length > 0) ?
37 | BluetoothService.bluetoothDeviceName : qsTr("Bluetooth"))
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/quickToggles/GameMode.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import "../"
4 | import Quickshell
5 | import Quickshell.Io
6 | import Quickshell.Hyprland
7 |
8 | QuickToggleButton {
9 | property bool enabled: false
10 | buttonIcon: "gamepad"
11 | toggled: enabled
12 |
13 | onClicked: {
14 | enabled = !enabled
15 | if (enabled) {
16 | // gameModeOn.running = true
17 | Quickshell.execDetached(["hyprctl", "--batch", "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"])
18 | } else {
19 | Quickshell.execDetached(["hyprctl reload"])
20 | }
21 | }
22 |
23 | StyledToolTip {
24 | text: qsTr("Game mode")
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/quickToggles/IdleInhibitor.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import "../"
4 | import Quickshell.Io
5 | import Quickshell
6 | import Quickshell.Hyprland
7 |
8 | QuickToggleButton {
9 | id: root
10 | toggled: false
11 | buttonIcon: "coffee"
12 | onClicked: {
13 | if (toggled) {
14 | root.toggled = false
15 | Quickshell.execDetached(["exec", "pkill", "wayland-idle"])
16 | } else {
17 | root.toggled = true
18 | Quickshell.execDetached(["python", "/usr/share/sleex/scripts/wayland-idle-inhibitor.py"])
19 | }
20 | }
21 | Process {
22 | id: fetchActiveState
23 | running: true
24 | command: ["bash", "-c", "pidof wayland-idle-inhibitor.py"]
25 | onExited: (exitCode, exitStatus) => {
26 | root.toggled = exitCode === 0
27 | }
28 | }
29 | StyledToolTip {
30 | text: qsTr("Keep system awake")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/quickToggles/NetworkToggle.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.services
3 | import qs.modules.common
4 | import qs.modules.common.widgets
5 | import qs.modules.common.functions
6 | import "../"
7 | import QtQuick
8 | import Quickshell
9 | import Quickshell.Io
10 | import Quickshell.Hyprland
11 |
12 | import Sleex.Services
13 |
14 | QuickToggleButton {
15 |
16 | toggled: Network.wifiEnabled
17 | buttonIcon: Network.wifiEnabled ? Network.getNetworkIcon(Network.active.strength ?? 0) : "wifi_off"
18 | onClicked: {
19 | Network.toggleWifi()
20 | }
21 | altAction: () => {
22 | Quickshell.execDetached(["bash", "-c", `${Network.ethernet ? Config.options.apps.networkEthernet : Config.options.apps.network}`])
23 | GlobalStates.dashboardOpen = false
24 | }
25 | StyledToolTip {
26 | text: StringUtils.format(qsTr("{0} | Right-click to configure"), Network.active.ssid)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/quickToggles/NightLight.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import qs.modules.common
3 | import qs.modules.common.widgets
4 | import qs
5 | import qs.services
6 | import Quickshell.Io
7 |
8 | QuickToggleButton {
9 | id: nightLightButton
10 | property bool enabled: NightLight.active
11 | toggled: enabled
12 | buttonIcon: Config.options.display.nightLightAuto ? "night_sight_auto" : "bedtime"
13 | onClicked: {
14 | NightLight.toggle()
15 | }
16 |
17 | altAction: () => {
18 | Config.options.display.nightLightAuto = !Config.options.display.nightLightAuto
19 | }
20 |
21 | Component.onCompleted: {
22 | NightLight.fetchState()
23 | }
24 |
25 | StyledToolTip {
26 | text: "Night Light | Right-click to toggle Auto mode"
27 | }
28 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/quickToggles/QuickToggleButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 | import Quickshell.Io
8 |
9 | GroupButton {
10 | id: button
11 | property string buttonIcon
12 | baseWidth: altAction ? 60 : 40
13 | baseHeight: 40
14 | clickedWidth: baseWidth + 20
15 | toggled: false
16 | buttonRadius: (altAction && toggled) ? Appearance?.rounding.normal : Math.min(baseHeight, baseWidth) / 2
17 | buttonRadiusPressed: Appearance?.rounding?.small
18 |
19 | contentItem: MaterialSymbol {
20 | anchors.centerIn: parent
21 | iconSize: Appearance.font.pixelSize.larger
22 | fill: toggled ? 1 : 0
23 | color: toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1
24 | horizontalAlignment: Text.AlignHCenter
25 | verticalAlignment: Text.AlignVCenter
26 | text: buttonIcon
27 |
28 | Behavior on color {
29 | animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/todo/TodoItemActionButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 |
8 | RippleButton {
9 | id: button
10 | property string buttonText: ""
11 | property string tooltipText: ""
12 |
13 | implicitHeight: 30
14 | implicitWidth: implicitHeight
15 |
16 | Behavior on implicitWidth {
17 | SmoothedAnimation {
18 | velocity: Appearance.animation.elementMove.velocity
19 | }
20 | }
21 |
22 | buttonRadius: Appearance.rounding.small
23 |
24 | contentItem: StyledText {
25 | text: buttonText
26 | horizontalAlignment: Text.AlignHCenter
27 | font.pixelSize: Appearance.font.pixelSize.larger
28 | color: Appearance.colors.colOnLayer1
29 | }
30 |
31 | StyledToolTip {
32 | text: tooltipText
33 | extraVisibleCondition: tooltipText.length > 0
34 | }
35 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dashboard/weather/WeatherOff.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 | import QtQuick.Controls
4 | import qs.modules.common
5 | import qs.modules.common.widgets
6 | import qs.services
7 |
8 | Rectangle {
9 | id: weatherRoot
10 | anchors.horizontalCenterOffset: -2
11 | color: "transparent"
12 |
13 | Rectangle {
14 | id: card
15 | anchors.fill: parent
16 | color: "transparent"
17 |
18 | ColumnLayout {
19 | anchors.fill: parent
20 | Text {
21 | text: "Weather disabled"
22 | color: Appearance.colors.colOnLayer1
23 | font.pixelSize: Appearance.font.pixelSize.title
24 | Layout.fillWidth: true
25 | horizontalAlignment: Text.AlignHCenter
26 | }
27 | // Separator line
28 | Rectangle {
29 | width: parent.width
30 | height: 1
31 | color: Appearance.colors.colLayer2
32 | Layout.fillWidth: true
33 | Layout.topMargin: 2
34 | Layout.bottomMargin: 2
35 | }
36 | Text {
37 | text: "The weather service is disabled.\nEnable it in the policy page of the Sleex settings."
38 | color: Appearance.colors.colOnLayer1
39 | font.pixelSize: Appearance.font.pixelSize.normal
40 | horizontalAlignment: Text.AlignHCenter
41 | wrapMode: Text.Wrap
42 | Layout.fillWidth: true
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/dock/DockButton.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.modules.common
3 | import qs.modules.common.widgets
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 |
8 | RippleButton {
9 | Layout.fillHeight: true
10 | Layout.topMargin: Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut
11 | implicitWidth: implicitHeight - topInset - bottomInset
12 | buttonRadius: Appearance.rounding.normal
13 |
14 | topInset: Appearance.sizes.hyprlandGapsOut + dockRow.padding
15 | bottomInset: Appearance.sizes.hyprlandGapsOut + dockRow.padding
16 | }
17 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/dock/DockSeparator.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.modules.common
3 | import QtQuick
4 | import QtQuick.Controls
5 | import QtQuick.Layouts
6 |
7 | Rectangle {
8 | Layout.topMargin: Appearance.sizes.elevationMargin + dockRow.padding + Appearance.rounding.normal
9 | Layout.bottomMargin: Appearance.sizes.hyprlandGapsOut + dockRow.padding + Appearance.rounding.normal
10 | Layout.fillHeight: true
11 | implicitWidth: 1
12 | color: Appearance.colors.colOutlineVariant
13 | }
14 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/lockscreen/pam/password.conf:
--------------------------------------------------------------------------------
1 | auth sufficient pam_fprintd.so
2 | auth required pam_unix.so
3 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/notificationPopup/NotificationPopup.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.modules.common
3 | import qs.modules.common.widgets
4 | import qs.services
5 | import QtQuick
6 | import QtQuick.Controls
7 | import QtQuick.Layouts
8 | import Quickshell
9 | import Quickshell.Wayland
10 | import Quickshell.Hyprland
11 |
12 | Scope {
13 | id: notificationPopup
14 |
15 | PanelWindow {
16 | id: root
17 | visible: (Notifications.popupList.length > 0)
18 | screen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) ?? null
19 |
20 | WlrLayershell.namespace: "quickshell:notificationPopup"
21 | WlrLayershell.layer: WlrLayer.Overlay
22 | exclusiveZone: 0
23 |
24 | anchors {
25 | top: true
26 | bottom: true
27 | }
28 |
29 | mask: Region {
30 | item: listview.contentItem
31 | }
32 |
33 | color: "transparent"
34 | implicitWidth: Appearance.sizes.notificationPopupWidth
35 |
36 | NotificationListView {
37 | id: listview
38 | anchors.top: parent.top
39 | anchors.bottom: parent.bottom
40 | anchors.horizontalCenter: parent.horizontalCenter
41 | anchors.topMargin: 5
42 | implicitWidth: parent.width - Appearance.sizes.elevationMargin * 2
43 | popup: true
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/session/SessionActionButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import QtQuick
5 | import QtQuick.Controls
6 | import QtQuick.Layouts
7 | import Quickshell
8 | import Quickshell.Io
9 |
10 | RippleButton {
11 | id: button
12 |
13 | property string buttonIcon
14 | property string buttonText
15 | property bool keyboardDown: false
16 | property real size: 120
17 |
18 | buttonRadius: (button.focus || button.down) ? size / 2 : Appearance.rounding.verylarge
19 | colBackground: button.keyboardDown ? Appearance.colors.colSecondaryContainerActive :
20 | button.focus ? Appearance.colors.colPrimary :
21 | Appearance.colors.colSecondaryContainer
22 | colBackgroundHover: Appearance.colors.colPrimary
23 | colRipple: Appearance.colors.colPrimaryActive
24 | property color colText: (button.down || button.keyboardDown || button.focus || button.hovered) ?
25 | Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer0
26 |
27 | Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
28 | background.implicitHeight: size
29 | background.implicitWidth: size
30 |
31 | Behavior on buttonRadius {
32 | animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
33 | }
34 |
35 | Keys.onPressed: (event) => {
36 | if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
37 | keyboardDown = true
38 | button.clicked()
39 | event.accepted = true;
40 | }
41 | }
42 | Keys.onReleased: (event) => {
43 | if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
44 | keyboardDown = false
45 | event.accepted = true;
46 | }
47 | }
48 |
49 | contentItem: MaterialSymbol {
50 | id: icon
51 | anchors.fill: parent
52 | color: button.colText
53 | horizontalAlignment: Text.AlignHCenter
54 | iconSize: 45
55 | text: buttonIcon
56 | }
57 |
58 | StyledToolTip {
59 | text: buttonText
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/sidebarLeft/ApiCommandButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import QtQuick
4 |
5 | GroupButton {
6 | id: button
7 | property string buttonText
8 |
9 | horizontalPadding: 8
10 | verticalPadding: 6
11 |
12 | baseWidth: contentItem.implicitWidth + horizontalPadding * 2
13 | clickedWidth: baseWidth + 20
14 | baseHeight: contentItem.implicitHeight + verticalPadding * 2
15 | buttonRadius: down ? Appearance.rounding.verysmall : Appearance.rounding.small
16 |
17 | colBackground: Appearance.colors.colLayer2
18 | colBackgroundHover: Appearance.colors.colLayer2Hover
19 | colBackgroundActive: Appearance.colors.colLayer2Active
20 |
21 | contentItem: StyledText {
22 | horizontalAlignment: Text.AlignHCenter
23 | text: buttonText
24 | color: Appearance.m3colors.m3onSurface
25 | }
26 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/sidebarLeft/ApiInputBoxIndicator.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 | import QtQuick.Layouts
6 |
7 | Item { // Model indicator
8 | id: root
9 | property string icon: "api"
10 | property string text: ""
11 | property string tooltipText: ""
12 | implicitHeight: rowLayout.implicitHeight + 4 * 2
13 | implicitWidth: rowLayout.implicitWidth + 4 * 2
14 |
15 | RowLayout {
16 | id: rowLayout
17 | anchors.centerIn: parent
18 |
19 | MaterialSymbol {
20 | text: root.icon
21 | iconSize: Appearance.font.pixelSize.normal
22 | }
23 | StyledText {
24 | id: providerName
25 | font.pixelSize: Appearance.font.pixelSize.smaller
26 | color: Appearance.m3colors.m3onSurface
27 | elide: Text.ElideRight
28 | text: root.text
29 | animateChange: true
30 | }
31 | }
32 |
33 | Loader {
34 | active: root.tooltipText?.length > 0
35 | anchors.fill: parent
36 | sourceComponent: MouseArea {
37 | id: mouseArea
38 | hoverEnabled: true
39 |
40 | StyledToolTip {
41 | id: toolTip
42 | extraVisibleCondition: false
43 | alternativeVisibleCondition: mouseArea.containsMouse // Show tooltip when hovered
44 | text: root.tooltipText
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/sidebarLeft/DescriptionBox.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.services
3 | import qs.modules.common
4 | import qs.modules.common.widgets
5 | import QtQuick
6 | import QtQuick.Layouts
7 |
8 | Item { // Tag suggestion description
9 | id: root
10 | property alias text: tagDescriptionText.text
11 | property bool showArrows: true
12 | property bool showTab: true
13 |
14 | visible: tagDescriptionText.text.length > 0
15 | Layout.fillWidth: true
16 | implicitHeight: tagDescriptionBackground.implicitHeight
17 |
18 | Rectangle {
19 | id: tagDescriptionBackground
20 | color: Appearance.colors.colLayer2
21 | anchors.fill: parent
22 | radius: Appearance.rounding.verysmall
23 | implicitHeight: descriptionRow.implicitHeight + 5 * 2
24 |
25 | RowLayout {
26 | id: descriptionRow
27 | spacing: 4
28 | anchors {
29 | fill: parent
30 | leftMargin: 10
31 | rightMargin: 10
32 | }
33 |
34 | StyledText {
35 | id: tagDescriptionText
36 | Layout.fillWidth: true
37 | font.pixelSize: Appearance.font.pixelSize.smaller
38 | color: Appearance.colors.colOnLayer2
39 | wrapMode: Text.Wrap
40 | }
41 | KeyboardKey {
42 | visible: root.showArrows
43 | key: "↑"
44 | }
45 | KeyboardKey {
46 | visible: root.showArrows
47 | key: "↓"
48 | }
49 | StyledText {
50 | visible: root.showArrows && root.showTab
51 | text: "or"
52 | font.pixelSize: Appearance.font.pixelSize.smaller
53 | }
54 | KeyboardKey {
55 | id: tagDescriptionKey
56 | visible: root.showTab
57 | key: "Tab"
58 | Layout.alignment: Qt.AlignVCenter
59 | }
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/sidebarLeft/SidebarLeftContent.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.services
3 | import qs.modules.common
4 | import qs.modules.common.widgets
5 | import QtQuick
6 | import QtQuick.Controls
7 | import QtQuick.Layouts
8 | import QtQuick.Effects
9 | import Qt5Compat.GraphicalEffects
10 | import Quickshell.Io
11 | import Quickshell
12 | import Quickshell.Widgets
13 | import Quickshell.Wayland
14 | import Quickshell.Hyprland
15 |
16 | Item {
17 | id: root
18 | required property var scopeRoot
19 | anchors.fill: parent
20 |
21 | ColumnLayout {
22 | anchors.fill: parent
23 | anchors.margins: sidebarPadding
24 |
25 | spacing: sidebarPadding
26 |
27 | SwipeView { // Content pages
28 | id: swipeView
29 | Layout.topMargin: 5
30 | Layout.fillWidth: true
31 | Layout.fillHeight: true
32 | spacing: 10
33 |
34 | contentChildren: [
35 | aiChat.createObject()
36 | ]
37 | }
38 |
39 | Component {
40 | id: aiChat
41 | AiChat {}
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/src/share/sleex/modules/sidebarLeft/aiChat/AiMessageControlButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.services
4 | import QtQuick
5 |
6 | GroupButton {
7 | id: button
8 | property string buttonIcon
9 | property bool activated: false
10 | toggled: activated
11 |
12 | baseWidth: height
13 |
14 | contentItem: MaterialSymbol {
15 | horizontalAlignment: Text.AlignHCenter
16 | iconSize: Appearance.font.pixelSize.larger
17 | text: buttonIcon
18 | color: button.activated ? Appearance.m3colors.m3onPrimary :
19 | button.enabled ? Appearance.m3colors.m3onSurface :
20 | Appearance.colors.colOnLayer1Inactive
21 |
22 | Behavior on color {
23 | animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.modules.common.widgets
3 | import qs.modules.common.functions
4 | import qs.services
5 | import QtQuick
6 | import QtQuick.Layouts
7 | import Quickshell.Hyprland
8 |
9 | RippleButton {
10 | id: root
11 | property string displayText
12 | property string url
13 |
14 | property real faviconSize: 20
15 | implicitHeight: 30
16 | leftPadding: (implicitHeight - faviconSize) / 2
17 | rightPadding: 10
18 | buttonRadius: Appearance.rounding.full
19 | colBackground: Appearance.colors.colSurfaceContainerHighest
20 | colBackgroundHover: Appearance.colors.colSurfaceContainerHighestHover
21 | colRipple: Appearance.colors.colSurfaceContainerHighestActive
22 |
23 | PointingHandInteraction {}
24 | onClicked: {
25 | if (url) {
26 | Qt.openUrlExternally(url)
27 | GlobalStates.sidebarLeftOpen = false
28 | }
29 | }
30 |
31 | contentItem: Item {
32 | anchors.centerIn: parent
33 | implicitWidth: rowLayout.implicitWidth
34 | implicitHeight: rowLayout.implicitHeight
35 | RowLayout {
36 | id: rowLayout
37 | anchors.fill: parent
38 | spacing: 5
39 | Favicon {
40 | url: root.url
41 | size: root.faviconSize
42 | displayText: root.displayText
43 | }
44 | StyledText {
45 | id: text
46 | horizontalAlignment: Text.AlignHCenter
47 | text: displayText
48 | color: Appearance.m3colors.m3onSurface
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/share/sleex/modules/sidebarLeft/aiChat/SearchQueryButton.qml:
--------------------------------------------------------------------------------
1 | import qs
2 | import qs.modules.common
3 | import qs.modules.common.widgets
4 | import qs.services
5 | import qs.modules.common.functions
6 | import QtQuick
7 | import QtQuick.Layouts
8 | import Quickshell.Hyprland
9 |
10 | RippleButton {
11 | id: root
12 | property string query
13 |
14 | implicitHeight: 30
15 | leftPadding: 6
16 | rightPadding: 10
17 | buttonRadius: Appearance.rounding.verysmall
18 | colBackground: Appearance.colors.colSurfaceContainerHighest
19 | colBackgroundHover: Appearance.colors.colSurfaceContainerHighestHover
20 | colRipple: Appearance.colors.colSurfaceContainerHighestActive
21 |
22 | PointingHandInteraction {}
23 | onClicked: {
24 | let url = Config.options.search.engineBaseUrl + root.query;
25 | for (let site of (Config?.options?.search.excludedSites ?? [])) {
26 | url += ` -site:${site}`;
27 | }
28 | Qt.openUrlExternally(url);
29 | GlobalStates.sidebarLeftOpen = false;
30 | }
31 |
32 | contentItem: Item {
33 | anchors.centerIn: parent
34 | implicitWidth: rowLayout.implicitWidth
35 | implicitHeight: rowLayout.implicitHeight
36 | RowLayout {
37 | id: rowLayout
38 | anchors.centerIn: parent
39 | spacing: 5
40 | MaterialSymbol {
41 | text: "search"
42 | iconSize: 20
43 | color: Appearance.m3colors.m3onSurface
44 | }
45 | StyledText {
46 | id: text
47 | horizontalAlignment: Text.AlignHCenter
48 | text: root.query
49 | color: Appearance.m3colors.m3onSurface
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/share/sleex/plugins/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(src/Sleex)
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(Qt6 REQUIRED COMPONENTS Core Qml Gui Quick Concurrent Sql Network DBus Bluetooth)
2 | find_package(PkgConfig REQUIRED)
3 |
4 | set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml")
5 | qt_standard_project_setup(REQUIRES 6.9)
6 |
7 | function(qml_module arg_TARGET)
8 | cmake_parse_arguments(PARSE_ARGV 1 arg "" "URI" "SOURCES;LIBRARIES")
9 |
10 | qt_add_qml_module(${arg_TARGET}
11 | URI ${arg_URI}
12 | VERSION ${VERSION}
13 | SOURCES ${arg_SOURCES}
14 | )
15 |
16 | qt_query_qml_module(${arg_TARGET}
17 | URI module_uri
18 | VERSION module_version
19 | PLUGIN_TARGET module_plugin_target
20 | TARGET_PATH module_target_path
21 | QMLDIR module_qmldir
22 | TYPEINFO module_typeinfo
23 | )
24 |
25 | message(STATUS "Created QML module ${module_uri}, version ${module_version}")
26 |
27 | set(module_dir "${INSTALL_QMLDIR}/${module_target_path}")
28 | install(TARGETS ${arg_TARGET} LIBRARY DESTINATION "${module_dir}" RUNTIME DESTINATION "${module_dir}")
29 | install(TARGETS "${module_plugin_target}" LIBRARY DESTINATION "${module_dir}" RUNTIME DESTINATION "${module_dir}")
30 | install(FILES "${module_qmldir}" DESTINATION "${module_dir}")
31 | install(FILES "${module_typeinfo}" DESTINATION "${module_dir}")
32 |
33 | target_link_libraries(${arg_TARGET} PRIVATE Qt::Core Qt::Qml ${arg_LIBRARIES})
34 | endfunction()
35 |
36 | add_subdirectory(services)
37 |
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | pkg_check_modules(LIBNM REQUIRED libnm)
2 | pkg_check_modules(GLIB REQUIRED glib-2.0 gobject-2.0 gio-2.0)
3 |
4 | qml_module(sleex-services
5 | URI Sleex.Services
6 | SOURCES
7 | resourceUsage.cpp resourceUsage.hpp
8 | network.cpp network.hpp
9 | bluetooth.cpp bluetooth.hpp
10 | plugin.cpp
11 | DEPENDENCIES
12 | Qt::Bluetooth
13 | )
14 |
15 | target_include_directories(sleex-services PRIVATE
16 | ${LIBNM_INCLUDE_DIRS}
17 | ${GLIB_INCLUDE_DIRS}
18 | )
19 |
20 | target_link_libraries(sleex-services PRIVATE
21 | ${LIBNM_LIBRARIES}
22 | ${GLIB_LIBRARIES}
23 | )
24 |
25 | target_compile_options(sleex-services PRIVATE
26 | ${LIBNM_CFLAGS_OTHER}
27 | ${GLIB_CFLAGS_OTHER}
28 | )
29 |
30 | target_link_libraries(sleex-services
31 | PRIVATE
32 | Qt6::Core
33 | Qt6::Qml
34 | Qt6::Bluetooth
35 | )
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/bluetooth.cpp:
--------------------------------------------------------------------------------
1 | #include "bluetooth.hpp"
2 |
3 | BluetoothService::BluetoothService(QObject *parent)
4 | : QObject(parent)
5 | {
6 | // Check for Bluetooth adapters
7 | const auto adapters = QBluetoothLocalDevice::allDevices();
8 | if (!adapters.isEmpty()) {
9 | m_localDevice = new QBluetoothLocalDevice(adapters.first().address(), this);
10 | m_available = true;
11 |
12 | connect(m_localDevice, &QBluetoothLocalDevice::hostModeStateChanged, this, [this](QBluetoothLocalDevice::HostMode mode) {
13 | bool enabled = (mode != QBluetoothLocalDevice::HostPoweredOff);
14 | if (m_enabled != enabled) {
15 | m_enabled = enabled;
16 | emit bluetoothEnabledChanged();
17 | }
18 | });
19 | } else {
20 | // No adapters at all
21 | m_available = false;
22 | }
23 | }
24 |
25 | void BluetoothService::update()
26 | {
27 | if (!m_available || !m_localDevice) {
28 | // Reset state if no adapter
29 | if (m_enabled) { m_enabled = false; emit bluetoothEnabledChanged(); }
30 | if (m_connected) { m_connected = false; emit bluetoothConnectedChanged(); }
31 | if (!m_deviceName.isEmpty()) { m_deviceName.clear(); emit bluetoothDeviceNameChanged(); }
32 | if (!m_deviceAddress.isEmpty()) { m_deviceAddress.clear(); emit bluetoothDeviceAddressChanged(); }
33 | return;
34 | }
35 |
36 | // Update enabled state
37 | bool enabled = (m_localDevice->hostMode() != QBluetoothLocalDevice::HostPoweredOff);
38 | if (m_enabled != enabled) {
39 | m_enabled = enabled;
40 | emit bluetoothEnabledChanged();
41 | }
42 |
43 | // If enabled, fetch connected device info (stubbed here, needs device discovery logic)
44 | // For now, just reset connected state
45 | if (!m_connected) {
46 | m_connected = false;
47 | emit bluetoothConnectedChanged();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/bluetooth.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class BluetoothService : public QObject {
9 | Q_OBJECT
10 | QML_SINGLETON
11 | QML_NAMED_ELEMENT(BluetoothService)
12 |
13 | Q_PROPERTY(bool bluetoothAvailable READ bluetoothAvailable NOTIFY bluetoothAvailableChanged FINAL)
14 | Q_PROPERTY(bool bluetoothEnabled READ bluetoothEnabled NOTIFY bluetoothEnabledChanged FINAL)
15 | Q_PROPERTY(bool bluetoothConnected READ bluetoothConnected NOTIFY bluetoothConnectedChanged FINAL)
16 | Q_PROPERTY(QString bluetoothDeviceName READ bluetoothDeviceName NOTIFY bluetoothDeviceNameChanged FINAL)
17 | Q_PROPERTY(QString bluetoothDeviceAddress READ bluetoothDeviceAddress NOTIFY bluetoothDeviceAddressChanged FINAL)
18 |
19 | public:
20 | explicit BluetoothService(QObject *parent = nullptr);
21 |
22 | bool bluetoothAvailable() const { return m_available; }
23 | bool bluetoothEnabled() const { return m_enabled; }
24 | bool bluetoothConnected() const { return m_connected; }
25 | QString bluetoothDeviceName() const { return m_deviceName; }
26 | QString bluetoothDeviceAddress() const { return m_deviceAddress; }
27 |
28 | Q_INVOKABLE void update();
29 |
30 | signals:
31 | void bluetoothAvailableChanged();
32 | void bluetoothEnabledChanged();
33 | void bluetoothConnectedChanged();
34 | void bluetoothDeviceNameChanged();
35 | void bluetoothDeviceAddressChanged();
36 |
37 | private:
38 | QBluetoothLocalDevice *m_localDevice = nullptr;
39 | bool m_available = false;
40 | bool m_enabled = false;
41 | bool m_connected = false;
42 | QString m_deviceName;
43 | QString m_deviceAddress;
44 | };
45 |
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/brightness.cpp:
--------------------------------------------------------------------------------
1 | #include "brightness.hpp"
2 | #include
3 | #include
4 | #include
5 |
6 | namespace sleex::services {
7 |
8 | Brightness::Brightness(QObject *parent): QObject(parent), m_value(50) {
9 | // Initialize with current brightness
10 | updateCurrentBrightness();
11 | }
12 |
13 | int Brightness::value() const {
14 | return m_value;
15 | }
16 |
17 | void Brightness::setValue(int val) {
18 | // Clamp value between 1 and 100
19 | val = qBound(1, val, 100);
20 |
21 | if (m_value == val)
22 | return;
23 |
24 | // Try to set brightness using brightnessctl
25 | QProcess process;
26 | process.start("brightnessctl", QStringList() << "s" << QString("%1%").arg(val) << "--quiet");
27 |
28 | if (process.waitForFinished(1000)) {
29 | if (process.exitCode() == 0) {
30 | m_value = val;
31 | emit valueChanged();
32 | return;
33 | }
34 | }
35 |
36 | qWarning() << "Failed to set brightness. Install 'brightnessctl'";
37 | }
38 |
39 | void Brightness::updateCurrentBrightness() {
40 | QProcess process;
41 | process.start("sh", QStringList() << "-c" << "echo \"$(brightnessctl g) $(brightnessctl m)\"");
42 |
43 | if (process.waitForFinished(1000) && process.exitCode() == 0) {
44 | QString output = QString::fromUtf8(process.readAllStandardOutput()).trimmed();
45 | QStringList parts = output.split(' ');
46 |
47 | if (parts.size() >= 2) {
48 | bool okCurrent, okMax;
49 | int current = parts[0].toInt(&okCurrent);
50 | int max = parts[1].toInt(&okMax);
51 |
52 | if (okCurrent && okMax && max > 0) {
53 | m_value = qRound((current * 100.0) / max);
54 | emit valueChanged();
55 | return;
56 | }
57 | }
58 | }
59 |
60 | qWarning() << "Could not read current brightness. Install 'brightnessctl'";
61 | }
62 |
63 | } // namespace sleex::services
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/brightness.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | namespace sleex::services {
6 |
7 | class Brightness : public QObject {
8 | Q_OBJECT
9 | QML_ELEMENT
10 | QML_SINGLETON
11 | Q_PROPERTY(int value READ value NOTIFY valueChanged)
12 |
13 | public:
14 | explicit Brightness(QObject *parent = nullptr);
15 |
16 | int value() const;
17 | Q_INVOKABLE void setValue(int v);
18 |
19 | signals:
20 | void valueChanged();
21 |
22 | private:
23 | void updateCurrentBrightness();
24 | int m_value;
25 | };
26 |
27 | } // namespace sleex::services
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/displays.hpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/plugins/src/Sleex/services/displays.hpp
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/meta_types/qt6sleex-services_metatypes.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/plugins/src/Sleex/services/meta_types/qt6sleex-services_metatypes.json
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/monitor.cpp:
--------------------------------------------------------------------------------
1 | #include "service.hpp"
2 | #include
3 |
4 | namespace sleex::services {
5 |
6 | Service::Service(QObject* parent)
7 | : QObject(parent) {}
8 |
9 | void Service::ref(QObject* sender) {
10 | if (!sender) {
11 | qWarning() << "Service::ref() called with null sender";
12 | return;
13 | }
14 |
15 | if (m_refs.contains(sender)) {
16 | qWarning() << "Service::ref() called multiple times for same sender";
17 | return;
18 | }
19 |
20 | if (m_refs.isEmpty()) {
21 | start();
22 | }
23 |
24 | // Connect to destroyed signal to auto-cleanup
25 | connect(sender, &QObject::destroyed, this, &Service::onRefDestroyed);
26 | m_refs.insert(sender);
27 | }
28 |
29 | void Service::unref(QObject* sender) {
30 | if (!sender) {
31 | qWarning() << "Service::unref() called with null sender";
32 | return;
33 | }
34 |
35 | if (!m_refs.contains(sender)) {
36 | qWarning() << "Service::unref() called for non-referenced sender";
37 | return;
38 | }
39 |
40 | // Disconnect to avoid double-unreferencing
41 | disconnect(sender, &QObject::destroyed, this, &Service::onRefDestroyed);
42 |
43 | m_refs.remove(sender);
44 |
45 | if (m_refs.isEmpty()) {
46 | stop();
47 | }
48 | }
49 |
50 | void Service::onRefDestroyed() {
51 | QObject* sender = QObject::sender();
52 | if (!sender) return;
53 |
54 | // Don't call unref() here to avoid recursion/disconnect issues
55 | // Just remove from set and check if empty
56 | if (m_refs.remove(sender) && m_refs.isEmpty()) {
57 | stop();
58 | }
59 | }
60 |
61 | } // namespace sleex::services
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/monitor.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "service.hpp"
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace sleex::services {
9 |
10 | struct Monitor {
11 | Q_GADGET
12 | Q_PROPERTY(int id MEMBER id)
13 | Q_PROPERTY(QString name MEMBER name)
14 | Q_PROPERTY(bool connected MEMBER connected)
15 |
16 | public:
17 | int id;
18 | QString name;
19 | bool connected;
20 | };
21 |
22 | class MonitorService : public Service {
23 | Q_OBJECT
24 | QML_ELEMENT
25 |
26 | Q_PROPERTY(QList monitors READ monitors NOTIFY monitorsChanged)
27 |
28 | public:
29 | explicit MonitorService(QObject* parent = nullptr);
30 |
31 | QList monitors() const;
32 | Q_INVOKABLE void refresh();
33 |
34 | signals:
35 | void monitorsChanged();
36 | void error(const QString& message);
37 |
38 | private:
39 | QList m_monitors;
40 | void scanMonitors();
41 | };
42 |
43 | }
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/plugin.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | class SleexServicesPlugin : public QQmlExtensionPlugin {
4 | Q_OBJECT
5 | Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
6 |
7 | public:
8 | void registerTypes(const char *uri) override {
9 | // QML_ELEMENT and QML_SINGLETON macros handle registration automatically
10 | Q_UNUSED(uri)
11 | }
12 | };
13 |
14 | #include "plugin.moc"
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/qmltypes/sleex-services_foreign_types.txt:
--------------------------------------------------------------------------------
1 | --foreign-types=/usr/lib/qt6/metatypes/qt6qml_relwithdebinfo_metatypes.json,/usr/lib/qt6/metatypes/qt6core_relwithdebinfo_metatypes.json,/usr/lib/qt6/metatypes/qt6network_relwithdebinfo_metatypes.json
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/sleex-servicesplugin_Sleex_ServicesPlugin.cpp:
--------------------------------------------------------------------------------
1 | // This file is autogenerated by CMake. Do not edit.
2 |
3 | #include
4 | #include
5 |
6 |
7 |
8 |
9 | QT_DECLARE_EXTERN_SYMBOL_VOID(qml_register_types_Sleex_Services)
10 |
11 | class Sleex_ServicesPlugin : public QQmlEngineExtensionPlugin
12 | {
13 | Q_OBJECT
14 | Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
15 |
16 | public:
17 | Sleex_ServicesPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent)
18 | {
19 |
20 | QT_KEEP_SYMBOL(qml_register_types_Sleex_Services)
21 | }
22 | };
23 |
24 |
25 |
26 | #include "sleex-servicesplugin_Sleex_ServicesPlugin.moc"
27 |
--------------------------------------------------------------------------------
/src/share/sleex/plugins/src/Sleex/services/sleex-servicesplugin_Sleex_ServicesPlugin_in.cpp:
--------------------------------------------------------------------------------
1 | // This file is autogenerated by CMake. Do not edit.
2 |
3 | #include
4 | #include
5 |
6 |
7 |
8 |
9 | $<$:QT_DECLARE_EXTERN_SYMBOL_VOID($)>
11 |
12 | class Sleex_ServicesPlugin : public QQmlEngineExtensionPlugin
13 | {
14 | Q_OBJECT
15 | Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
16 |
17 | public:
18 | Sleex_ServicesPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent)
19 | {
20 |
21 | $<$:QT_KEEP_SYMBOL($)>
23 | }
24 | };
25 |
26 |
27 |
28 | #include "sleex-servicesplugin_Sleex_ServicesPlugin.moc"
29 |
--------------------------------------------------------------------------------
/src/share/sleex/qml/Sleex/Services/qmldir:
--------------------------------------------------------------------------------
1 | module Sleex.Services
2 | linktarget sleex-servicesplugin
3 | optional plugin sleex-servicesplugin
4 | classname Sleex_ServicesPlugin
5 | typeinfo sleex-services.qmltypes
6 | prefer :/qt/qml/Sleex/Services/
7 |
8 |
--------------------------------------------------------------------------------
/src/share/sleex/qml/Sleex/Services/sleex-services_qml_module_dir_map.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | /usr/share/sleex/qml/Sleex/Services
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/ai/show-installed-ollama-models.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Get the list, skip the header, and extract the first column (model names)
4 | model_names=$(ollama list | tail -n +2 | awk '{print $1}')
5 |
6 | # Build a JSON array
7 | json_array="["
8 | for name in $model_names; do
9 | json_array+="\"$name\","
10 | done
11 |
12 | # Remove trailing comma and close the array
13 | json_array="${json_array%,}]"
14 |
15 | # Output the JSON array
16 | echo "$json_array"
--------------------------------------------------------------------------------
/src/share/sleex/scripts/cava/raw_output_config.txt:
--------------------------------------------------------------------------------
1 | [general]
2 | mode = waves
3 | framerate = 60
4 | autosens = 1
5 | bars = 50
6 |
7 | [output]
8 | method = raw
9 | raw_target = /dev/stdout
10 | data_format = ascii
11 | channels = mono
12 | mono_option = average
13 |
14 | [smoothing]
15 | noise_reduction = 20
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/colors/scheme_for_image.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import sys
3 | import cv2
4 | import numpy as np
5 |
6 | # Allowed scheme types
7 | SCHEMES = [
8 | "scheme-content",
9 | "scheme-expressive",
10 | "scheme-fidelity",
11 | "scheme-fruit-salad",
12 | "scheme-monochrome",
13 | "scheme-neutral",
14 | "scheme-rainbow",
15 | "scheme-tonal-spot"
16 | ]
17 |
18 | def image_colorfulness(image):
19 | # Based on Hasler and Süsstrunk's colorfulness metric
20 | (B, G, R) = cv2.split(image.astype("float"))
21 | rg = np.absolute(R - G)
22 | yb = np.absolute(0.5 * (R + G) - B)
23 | std_rg = np.std(rg)
24 | std_yb = np.std(yb)
25 | mean_rg = np.mean(rg)
26 | mean_yb = np.mean(yb)
27 | colorfulness = np.sqrt(std_rg ** 2 + std_yb ** 2) + (0.3 * np.sqrt(mean_rg ** 2 + mean_yb ** 2))
28 | return colorfulness
29 |
30 | # scheme-content respects the image's colors very well, but it might
31 | # look too saturated, so we only use it for not very colorful images to be safe
32 | def pick_scheme(colorfulness):
33 | if colorfulness < 10:
34 | # return "scheme-monochrome"
35 | return "scheme-content"
36 | elif colorfulness < 20:
37 | return "scheme-content"
38 | elif colorfulness < 50:
39 | return "scheme-neutral"
40 | else:
41 | return "scheme-tonal-spot"
42 |
43 | def main():
44 | colorfulness_mode = False
45 | args = sys.argv[1:]
46 | if '--colorfulness' in args:
47 | colorfulness_mode = True
48 | args.remove('--colorfulness')
49 | if len(args) < 1:
50 | print("scheme-tonal-spot")
51 | sys.exit(1)
52 | img_path = args[0]
53 | img = cv2.imread(img_path)
54 | if img is None:
55 | print("scheme-tonal-spot")
56 | sys.exit(1)
57 | colorfulness = image_colorfulness(img)
58 | if colorfulness_mode:
59 | print(f"{colorfulness}")
60 | else:
61 | scheme = pick_scheme(colorfulness)
62 | print(scheme)
63 |
64 | if __name__ == "__main__":
65 | main()
--------------------------------------------------------------------------------
/src/share/sleex/scripts/firstRun.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This script is run the first time the user logs in after installing Sleex.
4 | # It sets up the user's environment to use Sleex.
5 |
6 | CONFIG_FILE="$HOME/.config/hypr/custom/general.conf"
7 | KEYBINDS_DIR="$HOME/.config/hypr/hyprland"
8 | VC_KEYMAP=$(grep -i KEYMAP /etc/vconsole.conf | cut -d= -f2 | tr -d '"')
9 | LAYOUT=$(echo "$VC_KEYMAP" | awk '{print tolower($0)}')
10 |
11 | echo "Setting keyboard layout to '$LAYOUT' in $CONFIG_FILE."
12 |
13 | if grep -q "^input:kb_layout" "$CONFIG_FILE"; then
14 | sed -i "s/^input:kb_layout.*/input:kb_layout = $LAYOUT/" "$CONFIG_FILE"
15 | else
16 | echo "input:kb_layout = $LAYOUT" >> "$CONFIG_FILE"
17 | fi
18 |
19 | echo "Applying keybinds configuration in $KEYBINDS_DIR."
20 |
21 | if [[ "$LAYOUT" == "us" ]]; then
22 | mv -f "$KEYBINDS_DIR/keybinds_us.conf" "$KEYBINDS_DIR/keybinds.conf"
23 | echo "Switched to US keybinds."
24 | elif [[ "$LAYOUT" == "fr" ]]; then
25 | mv -f "$KEYBINDS_DIR/keybinds_fr.conf" "$KEYBINDS_DIR/keybinds.conf"
26 | echo "Switched to FR keybinds."
27 | else
28 | echo "Unknown layout: $LAYOUT – applying US keybinds."
29 | mv -f "$KEYBINDS_DIR/keybinds_us.conf" "$KEYBINDS_DIR/keybinds.conf"
30 | fi
31 |
32 | if lsmod | grep -q '^nvidia'; then
33 | echo "Nvidia GPU found"
34 | {
35 | echo "env = LIBVA_DRIVER_NAME,nvidia"
36 | echo "env = __GLX_VENDOR_LIBRARY_NAME,nvidia"
37 | } >> ~/.config/hypr/custom/env.conf
38 | fi
39 |
40 | hyprctl reload
41 |
42 | echo 'Complete!'
--------------------------------------------------------------------------------
/src/share/sleex/scripts/hyprland/workspace_action.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | hyprctl dispatch "$1" $(((($(hyprctl activeworkspace -j | jq -r .id) - 1) / 10) * 10 + $2))
--------------------------------------------------------------------------------
/src/share/sleex/scripts/kvantum/materialQT.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
4 | XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
5 | XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
6 | CONFIG_DIR="/usr/share/sleex"
7 | CACHE_DIR="$XDG_CACHE_HOME/sleex"
8 | STATE_DIR="$XDG_STATE_HOME/sleex"
9 |
10 | get_light_dark() {
11 | current_mode=$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null | tr -d "'")
12 | if [[ "$current_mode" == "prefer-dark" ]]; then
13 | echo "dark"
14 | else
15 | echo "light"
16 | fi
17 | }
18 |
19 | apply_qt() {
20 | # Check if the theme exists
21 | FOLDER_PATH="$XDG_CONFIG_HOME/Kvantum/Colloid/"
22 |
23 | if [ ! -d "$FOLDER_PATH" ]; then
24 | # Send a notification
25 | notify-send "Colloid-kde theme required" " The folder '$FOLDER_PATH' does not exist."
26 | exit 1 # Exit the function if the folder does not exist
27 | fi
28 |
29 | lightdark=$(get_light_dark)
30 | if [ "$lightdark" = "light" ]; then
31 | # apply ligght colors
32 | cp "$XDG_CONFIG_HOME/Kvantum/Colloid/Colloid.kvconfig" "$XDG_CONFIG_HOME/Kvantum/MaterialAdw/MaterialAdw.kvconfig"
33 | python "$CONFIG_DIR/scripts/kvantum/adwsvg.py"
34 |
35 | else
36 | #apply dark colors
37 | cp "$XDG_CONFIG_HOME/Kvantum/Colloid/ColloidDark.kvconfig" "$XDG_CONFIG_HOME/Kvantum/MaterialAdw/MaterialAdw.kvconfig"
38 | python "$CONFIG_DIR/scripts/kvantum/adwsvgDark.py"
39 | fi
40 | }
41 |
42 | apply_qt
43 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/record-script.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | getdate() {
4 | date '+%Y-%m-%d_%H.%M.%S'
5 | }
6 | getaudiooutput() {
7 | pactl list sources | grep 'Name' | grep 'monitor' | cut -d ' ' -f2
8 | }
9 | getactivemonitor() {
10 | hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name'
11 | }
12 |
13 | xdgvideo="$(xdg-user-dir VIDEOS)"
14 | if [[ $xdgvideo = "$HOME" ]]; then
15 | unset xdgvideo
16 | fi
17 | mkdir -p "${xdgvideo:-$HOME/Videos}"
18 | cd "${xdgvideo:-$HOME/Videos}" || exit
19 |
20 | if pgrep wf-recorder > /dev/null; then
21 | notify-send "Recording Stopped" "Stopped" -a 'Recorder' &
22 | pkill wf-recorder &
23 | else
24 | if [[ "$1" == "--fullscreen-sound" ]]; then
25 | notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder'
26 | wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --audio="$(getaudiooutput)" & disown
27 | elif [[ "$1" == "--fullscreen" ]]; then
28 | notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder'
29 | wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t & disown
30 | else
31 | if ! region="$(slurp 2>&1)"; then
32 | notify-send "Recording cancelled" "Selection was cancelled" -a 'Recorder'
33 | exit 1
34 | fi
35 | notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'Recorder'
36 | if [[ "$1" == "--sound" ]]; then
37 | wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" --audio="$(getaudiooutput)" & disown
38 | else
39 | wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$region" & disown
40 | fi
41 | fi
42 | fi
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/gtk/gtk-colors.css:
--------------------------------------------------------------------------------
1 | /*
2 | * GTK Colors
3 | */
4 |
5 | @define-color accent_color {{ $primary }};
6 | @define-color accent_fg_color {{ $onPrimary }};
7 | @define-color accent_bg_color {{ $primary }};
8 | @define-color window_bg_color {{ $background }};
9 | @define-color window_fg_color {{ $onBackground }};
10 | @define-color headerbar_bg_color {{ $surfaceDim }};
11 | @define-color headerbar_fg_color {{ $onSurface }};
12 | @define-color popover_bg_color {{ $surfaceDim }};
13 | @define-color popover_fg_color {{ $onSurface }};
14 | @define-color view_bg_color {{ $surface }};
15 | @define-color view_fg_color {{ $onSurface }};
16 | @define-color card_bg_color {{ $surface }};
17 | @define-color card_fg_color {{ $onSurface }};
18 | @define-color sidebar_bg_color @window_bg_color;
19 | @define-color sidebar_fg_color @window_fg_color;
20 | @define-color sidebar_border_color @window_bg_color;
21 | @define-color sidebar_backdrop_color @window_bg_color;
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/term_emus/alacritty.tpl:
--------------------------------------------------------------------------------
1 | [colors.primary]
2 | background = "{background}"
3 | foreground = "{onBackground}"
4 |
5 | [colors.cursor]
6 | text = "{background}"
7 | cursor = "{onBackground}"
8 |
9 | [colors.vi_mode_cursor]
10 | text = "{background}"
11 | cursor = "{onBackground}"
12 |
13 | [colors.search.matches]
14 | foreground = "{term0}"
15 | background = "{term15}"
16 |
17 | [colors.search.focused_match]
18 | foreground = "CellBackground"
19 | background = "CellForeground"
20 |
21 | [colors.line_indicator]
22 | foreground = "None"
23 | background = "None"
24 |
25 | [colors.footer_bar]
26 | foreground = "{term8}"
27 | background = "{term7}"
28 |
29 | [colors.selection]
30 | text = "CellBackground"
31 | background = "CellForeground"
32 |
33 | [colors.normal]
34 | black = "{term0}"
35 | red = "{term1}"
36 | green = "{term2}"
37 | yellow = "{term3}"
38 | blue = "{term4}"
39 | magenta = "{term5}"
40 | cyan = "{term6}"
41 | white = "{term7}"
42 |
43 | [colors.bright]
44 | black = "{term8}"
45 | red = "{term9}"
46 | green = "{term10}"
47 | yellow = "{term11}"
48 | blue = "{term12}"
49 | magenta = "{term13}"
50 | cyan = "{term14}"
51 | white = "{term15}"
52 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/term_emus/foot.tpl:
--------------------------------------------------------------------------------
1 | [colors]
2 | background={background}
3 | foreground={onBackground}
4 | regular0={term0}
5 | regular1={term1}
6 | regular2={term2}
7 | regular3={term3}
8 | regular4={term4}
9 | regular5={term5}
10 | regular6={term6}
11 | regular7={term7}
12 | bright0={term8}
13 | bright1={term9}
14 | bright2={term10}
15 | bright3={term11}
16 | bright4={term12}
17 | bright5={term13}
18 | bright6={term14}
19 | bright7={term15}
20 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/term_emus/ghostty.tpl:
--------------------------------------------------------------------------------
1 | # pywal theme for ghostty
2 |
3 | background = {background}
4 | foreground = {onBackground}
5 | cursor-color = {onBackground}
6 | selection-background = {onBackground}
7 | selection-foreground = {background}
8 |
9 | palette = 0={term0}
10 | palette = 1={term1}
11 | palette = 2={term2}
12 | palette = 3={term3}
13 | palette = 4={term4}
14 | palette = 5={term5}
15 | palette = 6={term6}
16 | palette = 7={term7}
17 | palette = 8={term8}
18 | palette = 9={term9}
19 | palette = 10={term10}
20 | palette = 11={term11}
21 | palette = 12={term12}
22 | palette = 13={term13}
23 | palette = 14={term14}
24 | palette = 15={term15}
25 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/term_emus/kitty.tpl:
--------------------------------------------------------------------------------
1 | foreground {onBackground}
2 | background {background}
3 | cursor {onBackground}
4 |
5 | active_tab_foreground {background}
6 | active_tab_background {onBackground}
7 | inactive_tab_foreground {onBackground}
8 | inactive_tab_background {background}
9 | background_opacity 0.7
10 |
11 | active_border_color {onBackground}
12 | inactive_border_color {background}
13 | bell_border_color {term1}
14 |
15 | color0 {term0}
16 | color8 {term8}
17 | color1 {term1}
18 | color9 {term9}
19 | color2 {term2}
20 | color10 {term10}
21 | color3 {term3}
22 | color11 {term11}
23 | color4 {term4}
24 | color12 {term12}
25 | color5 {term5}
26 | color13 {term13}
27 | color6 {term6}
28 | color14 {term14}
29 | color7 {term7}
30 | color15 {term15}
31 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/term_emus/wezterm.tpl:
--------------------------------------------------------------------------------
1 | [colors]
2 | foreground = "{onBackground}"
3 | background = "{background}"
4 | cursor_bg = "{background}"
5 | cursor_border = "{term0}"
6 | cursor_fg = "{onBackground}"
7 |
8 | ansi = ["{term0}", "{term1}", "{term2}", "{term3}",
9 | "{term4}", "{term5}", "{term6}", "{term7}"]
10 |
11 | brights = ["{term8}", "{term9}", "{term10}", "{term11}",
12 | "{term12}", "{term13}", "{term14}", "{term15}"]
13 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/term_emus/zellij.tpl:
--------------------------------------------------------------------------------
1 | themes {
2 | py-matyou-wal-zellij {
3 | fg "{onBackground}"
4 | bg "{background}"
5 | black "{term0}"
6 | red "{term1}"
7 | green "{term2}"
8 | yellow "{term3}"
9 | blue "{term4}"
10 | magenta "{term5}"
11 | cyan "{term6}"
12 | white "{term7}"
13 | orange "{term9}"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/terminal/scheme-base.json:
--------------------------------------------------------------------------------
1 | {
2 | "dark": {
3 | "term0" : "#282828",
4 | "term1" : "#CC241D",
5 | "term2" : "#98971A",
6 | "term3" : "#D79921",
7 | "term4" : "#458588",
8 | "term5" : "#B16286",
9 | "term6" : "#689D6A",
10 | "term7" : "#A89984",
11 | "term8" : "#928374",
12 | "term9" : "#FB4934",
13 | "term10" : "#B8BB26",
14 | "term11" : "#FABD2F",
15 | "term12" : "#83A598",
16 | "term13" : "#D3869B",
17 | "term14" : "#8EC07C",
18 | "term15" : "#EBDBB2"
19 | },
20 | "light": {
21 | "term0" : "#FDF9F3",
22 | "term1" : "#FF6188",
23 | "term2" : "#A9DC76",
24 | "term3" : "#FC9867",
25 | "term4" : "#FFD866",
26 | "term5" : "#F47FD4",
27 | "term6" : "#78DCE8",
28 | "term7" : "#333034",
29 | "term8" : "#121212",
30 | "term9" : "#FF6188",
31 | "term10" : "#A9DC76",
32 | "term11" : "#FC9867",
33 | "term12" : "#FFD866",
34 | "term13" : "#F47FD4",
35 | "term14" : "#78DCE8",
36 | "term15" : "#333034"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/terminal/scheme-monochrome.json:
--------------------------------------------------------------------------------
1 | {
2 | "dark": {
3 | "term0": "#000000",
4 | "term1": "#FFFFFF",
5 | "term2": "#CCCCCC",
6 | "term3": "#8f8f8f",
7 | "term4": "#FFFFFF",
8 | "term5": "#111111",
9 | "term6": "#CCCCCC",
10 | "term7": "#FFFFFF",
11 | "term8": "#404040",
12 | "term9": "#CCCCCC",
13 | "term10": "#FFFFFF",
14 | "term11": "#909090",
15 | "term12": "#CCCCCC",
16 | "term13": "#808080",
17 | "term14": "#CCCCCC",
18 | "term15": "#FFFFFF"
19 | },
20 | "light": {
21 | "term0": "#EAE9EA",
22 | "term1": "#777777",
23 | "term2": "#000000",
24 | "term3": "#000000",
25 | "term4": "#000000",
26 | "term5": "#000000",
27 | "term6": "#000000",
28 | "term7": "#202020",
29 | "term8": "#000000",
30 | "term9": "#000000",
31 | "term10": "#CCCCCC",
32 | "term11": "#808080",
33 | "term12": "#CCCCCC",
34 | "term13": "#FFFFFF"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/templates/terminal/sequences.txt:
--------------------------------------------------------------------------------
1 | ]4;0;#$term0 #\]4;1;#$term1 #\]4;2;#$term2 #\]4;3;#$term3 #\]4;4;#$term4 #\]4;5;#$term5 #\]4;6;#$term6 #\]4;7;#$term7 #\]4;8;#$term8 #\]4;9;#$term9 #\]4;10;#$term10 #\]4;11;#$term11 #\]4;12;#$term12 #\]4;13;#$term13 #\]4;14;#$term14 #\]4;15;#$term15 #\]10;#$term7 #\]11;[$alpha]#$term0 #\]12;#$term7 #\]13;#$term7 #\]17;#$term7 #\]19;#$term0 #\]4;232;#$term7 #\]4;256;#$term7 #\]708;[$alpha]#$term0 #\
2 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/terminal/scheme-base.json:
--------------------------------------------------------------------------------
1 | {
2 | "dark": {
3 | "term0" : "#282828",
4 | "term1" : "#CC241D",
5 | "term2" : "#98971A",
6 | "term3" : "#D79921",
7 | "term4" : "#458588",
8 | "term5" : "#B16286",
9 | "term6" : "#689D6A",
10 | "term7" : "#A89984",
11 | "term8" : "#928374",
12 | "term9" : "#FB4934",
13 | "term10" : "#B8BB26",
14 | "term11" : "#FABD2F",
15 | "term12" : "#83A598",
16 | "term13" : "#D3869B",
17 | "term14" : "#8EC07C",
18 | "term15" : "#EBDBB2"
19 | },
20 | "light": {
21 | "term0" : "#FDF9F3",
22 | "term1" : "#FF6188",
23 | "term2" : "#A9DC76",
24 | "term3" : "#FC9867",
25 | "term4" : "#FFD866",
26 | "term5" : "#F47FD4",
27 | "term6" : "#78DCE8",
28 | "term7" : "#333034",
29 | "term8" : "#121212",
30 | "term9" : "#FF6188",
31 | "term10" : "#A9DC76",
32 | "term11" : "#FC9867",
33 | "term12" : "#FFD866",
34 | "term13" : "#F47FD4",
35 | "term14" : "#78DCE8",
36 | "term15" : "#333034"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/share/sleex/scripts/terminal/sequences.txt:
--------------------------------------------------------------------------------
1 | ]4;0;#$term0 #\]1;0;#$term0 #\]4;1;#$term1 #\]4;2;#$term2 #\]4;3;#$term3 #\]4;4;#$term4 #\]4;5;#$term5 #\]4;6;#$term6 #\]4;7;#$term7 #\]4;8;#$term8 #\]4;9;#$term9 #\]4;10;#$term10 #\]4;11;#$term11 #\]4;12;#$term12 #\]4;13;#$term13 #\]4;14;#$term14 #\]4;15;#$term15 #\]10;#$term7 #\]11;[100]#$term0 #\]12;#$term7 #\]13;#$term7 #\]17;#$term7 #\]19;#$term0 #\]4;232;#$term7 #\]4;256;#$term7 #\]708;[100]#$term0 #\]11;#$term0 #\
--------------------------------------------------------------------------------
/src/share/sleex/services/AiMessageData.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick;
3 |
4 | /**
5 | * Represents a message in an AI conversation. (Kind of) follows the OpenAI API message structure.
6 | */
7 | QtObject {
8 | property string role
9 | property string content
10 | property string model
11 | property bool thinking: true
12 | property bool done: false
13 | property var annotations: []
14 | property var annotationSources: []
15 | property string functionName
16 | property string functionCall
17 | property string functionResponse
18 | property bool visibleToUser: true
19 | }
20 |
--------------------------------------------------------------------------------
/src/share/sleex/services/Emojis.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 | pragma ComponentBehavior: Bound
3 |
4 | import qs.modules.common.functions
5 | import qs.modules.common
6 | import QtQuick
7 | import Quickshell
8 | import Quickshell.Io
9 |
10 | /**
11 | * Emojis.
12 | */
13 | Singleton {
14 | id: root
15 | property string emojiScriptPath: `/bin/fuzzel-emoji`
16 | property string lineBeforeData: "### DATA ###"
17 | property list list
18 | readonly property var preparedEntries: list.map(a => ({
19 | name: Fuzzy.prepare(`${a}`),
20 | entry: a
21 | }))
22 | function fuzzyQuery(search: string): var {
23 | if (root.sloppySearch) {
24 | const results = entries.slice(0, 100).map(str => ({
25 | entry: str,
26 | score: Levendist.computeTextMatchScore(str.toLowerCase(), search.toLowerCase())
27 | })).filter(item => item.score > root.scoreThreshold)
28 | .sort((a, b) => b.score - a.score)
29 | return results
30 | .map(item => item.entry)
31 | }
32 |
33 | return Fuzzy.go(search, preparedEntries, {
34 | all: true,
35 | key: "name"
36 | }).map(r => {
37 | return r.obj.entry
38 | });
39 | }
40 |
41 | function load() {
42 | emojiFileView.reload()
43 | }
44 |
45 | function updateEmojis(fileContent) {
46 | const lines = fileContent.split("\n")
47 | const dataIndex = lines.indexOf(root.lineBeforeData)
48 | if (dataIndex === -1) {
49 | console.warn("No data section found in emoji script file.")
50 | return
51 | }
52 | const emojis = lines.slice(dataIndex + 1).filter(line => line.trim() !== "")
53 | root.list = emojis.map(line => line.trim())
54 | }
55 |
56 | FileView {
57 | id: emojiFileView
58 | path: Qt.resolvedUrl(root.emojiScriptPath)
59 | onLoadedChanged: {
60 | const fileContent = emojiFileView.text()
61 | root.updateEmojis(fileContent)
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/share/sleex/services/FirstRunExperience.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 |
3 | import qs.modules.common.functions
4 | import qs.modules.common
5 | import Quickshell
6 | import Quickshell.Io
7 | import Quickshell.Hyprland
8 |
9 | Singleton {
10 | id: root
11 | property string firstRunFilePath: `${Directories.state}/sleex/user/first_run.txt`
12 | property string firstRunScriptPath: `/usr/share/sleex/scripts/firstRun.sh`
13 | property string firstRunFileContent: "This file is just here to confirm you've been greeted :>"
14 | property string defaultWallpaperPath: FileUtils.trimFileProtocol(`/usr/share/sleex/wallpapers/SleexOne.png`)
15 | property string welcomeNotifTitle: "Welcome to Sleex!"
16 | property string welcomeNotifBody: "First run? 👀 For a list of keybinds, hit Super + F1"
17 |
18 | function load() {
19 | firstRunFileView.reload()
20 | }
21 |
22 | function enableNextTime() {
23 | Quickshell.execDetached(["bash", "-c", `rm -f ${root.firstRunFilePath}`])
24 | }
25 | function disableNextTime() {
26 | Quickshell.execDetached(["bash", "-c", `echo ${root.firstRunFileContent} > ${root.firstRunFilePath}`])
27 | }
28 |
29 | function handleFirstRun() {
30 | Quickshell.execDetached(["bash", "-c", `${Directories.wallpaperSwitchScriptPath} ${root.defaultWallpaperPath} --mode dark`])
31 | Quickshell.execDetached(["sh", `${root.firstRunScriptPath}`])
32 | Quickshell.execDetached(['bash', '-c', `sleep 0.5; notify-send '${root.welcomeNotifTitle}' '${root.welcomeNotifBody}' -a 'Sleex' &`])
33 | //Quickshell.reload(true)
34 | }
35 |
36 |
37 | FileView {
38 | id: firstRunFileView
39 | path: Qt.resolvedUrl(firstRunFilePath)
40 | onLoadFailed: (error) => {
41 | if (error == FileViewError.FileNotFound) {
42 | root.handleFirstRun()
43 | firstRunFileView.setText(root.firstRunFileContent)
44 | }
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/share/sleex/services/Github.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.services
3 | import QtQuick
4 | import Quickshell
5 | import Quickshell.Io
6 | pragma Singleton
7 | pragma ComponentBehavior: Bound
8 |
9 | Singleton {
10 | id: root
11 | property int contribution_number
12 | property string author: Config.options.dashboard.ghUsername
13 | property var contributions: []
14 |
15 | Timer {
16 | interval: 600000 // 10 minutes
17 | running: true
18 | repeat: true
19 | onTriggered: getContributions.running = true
20 | }
21 |
22 | Process {
23 | id: getContributions
24 | running: true
25 | command: ["curl", `https://github-contributions-api.jogruber.de/v4/${root.author}`]
26 | stdout: StdioCollector {
27 | onStreamFinished: {
28 | const json = JSON.parse(text)
29 | const year = DateTime.year
30 | // Calculate total contributions in the last 365 days
31 | const oneYearAgo = new Date();
32 | oneYearAgo.setDate(oneYearAgo.getDate() - 365);
33 | root.contribution_number = json.contributions
34 | .filter(c => new Date(c.date) >= oneYearAgo)
35 | .reduce((sum, c) => sum + c.count, 0);
36 |
37 | const allContribs = json.contributions;
38 | const today = new Date();
39 | const cutoff = new Date(today);
40 | cutoff.setDate(cutoff.getDate() - 280);
41 |
42 | const recentContribs = allContribs
43 | .filter(c => new Date(c.date) >= cutoff)
44 | .sort((a, b) => new Date(a.date) - new Date(b.date));
45 |
46 | root.contributions = recentContribs;
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/share/sleex/services/MaterialThemeLoader.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 | pragma ComponentBehavior: Bound
3 |
4 | import qs.modules.common
5 | import QtQuick
6 | import Quickshell
7 | import Quickshell.Io
8 |
9 | /**
10 | * Automatically reloads generated material colors.
11 | * It is necessary to run reapplyTheme() on startup because Singletons are lazily loaded.
12 | */
13 | Singleton {
14 | id: root
15 | property string filePath: Directories.generatedMaterialThemePath
16 |
17 | function reapplyTheme() {
18 | themeFileView.reload()
19 | }
20 |
21 | function applyColors(fileContent) {
22 | const json = JSON.parse(fileContent)
23 | for (const key in json) {
24 | if (json.hasOwnProperty(key)) {
25 | // Convert snake_case to CamelCase
26 | const camelCaseKey = key.replace(/_([a-z])/g, (g) => g[1].toUpperCase())
27 | const m3Key = `m3${camelCaseKey}`
28 | Appearance.m3colors[m3Key] = json[key]
29 | }
30 | }
31 |
32 | Appearance.m3colors.darkmode = (Appearance.m3colors.m3background.hslLightness < 0.5)
33 | }
34 |
35 | Timer {
36 | id: delayedFileRead
37 | interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100
38 | repeat: false
39 | running: false
40 | onTriggered: {
41 | root.applyColors(themeFileView.text())
42 | }
43 | }
44 |
45 | FileView {
46 | id: themeFileView
47 | path: Qt.resolvedUrl(root.filePath)
48 | watchChanges: true
49 | onFileChanged: {
50 | this.reload()
51 | delayedFileRead.start()
52 | }
53 | onLoadedChanged: {
54 | const fileContent = themeFileView.text()
55 | root.applyColors(fileContent)
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/share/sleex/services/Quotes.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import qs.services
3 | import QtQuick
4 | import Quickshell
5 | import Quickshell.Io
6 | pragma Singleton
7 | pragma ComponentBehavior: Bound
8 |
9 | Singleton {
10 | id: root
11 | property string quote
12 | property string author
13 |
14 | Process {
15 | id: getQuote
16 | running: true
17 | command: ["curl", "https://quotes-api-self.vercel.app/quote"]
18 | stdout: StdioCollector {
19 | onStreamFinished: {
20 | const json = JSON.parse(text)
21 | root.quote = json.quote
22 | root.author = json.author
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/share/sleex/services/Wallpapers.qml:
--------------------------------------------------------------------------------
1 | import qs.modules.common
2 | import QtQuick
3 | import Quickshell
4 | import Quickshell.Io
5 | pragma Singleton
6 | pragma ComponentBehavior: Bound
7 |
8 | Singleton {
9 | id: root
10 | property var wallpaperList: []
11 |
12 | property string wallpaperPath: Config.options.background.wallpaperSelectorPath.lenght != 0 ? Config.options.background.wallpaperSelectorPath : Directories.wallpaperPath
13 |
14 | Process {
15 | id: listWallpapers
16 | running: true
17 | command: [
18 | "bash", "-c",
19 | "find " + root.wallpaperPath + " -type f \\( -iname '*.jpg' -o -iname '*.png' -o -iname '*.webp' \\) -printf '%P\\n'"
20 | ]
21 | stdout: StdioCollector {
22 | onStreamFinished: {
23 | root.wallpaperList = text.split('\n').filter(function(item) { return item.length > 0; });
24 | }
25 | }
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/src/share/sleex/services/Ydotool.qml:
--------------------------------------------------------------------------------
1 | pragma Singleton
2 |
3 | import qs.modules.common
4 | import Quickshell
5 | import Quickshell.Io
6 | import Quickshell.Hyprland
7 |
8 | Singleton {
9 | id: root
10 | property int shiftMode: 0 // 0: off, 1: on, 2: lock
11 | property list shiftKeys: [42, 54] // Keycodes for Shift keys (left and right)
12 | property list altKeys: [56, 100] // Keycodes for Alt keys (left and right)
13 | property list ctrlKeys: [29, 97] // Keycodes for Ctrl keys (left and right)
14 |
15 | onShiftModeChanged: {
16 | if (shiftMode === 0) {
17 |
18 | }
19 | }
20 |
21 | function releaseAllKeys() {
22 | const keycodes = Array.from(Array(249).keys());
23 | const releaseCommand = `ydotool key --key-delay 0 ${keycodes.map(keycode => `${keycode}:0`).join(" ")}`
24 | Quickshell.execDetached(["bash", "-c", `${releaseCommand}`])
25 | root.shiftMode = 0; // Reset shift mode
26 | }
27 |
28 | function releaseShiftKeys() {
29 | const releaseCommand = `ydotool key --key-delay 0 ${root.shiftKeys.map(keycode => `${keycode}:0`).join(" ")}`
30 | Quickshell.execDetached(["bash", "-c", `${releaseCommand}`])
31 | root.shiftMode = 0; // Reset shift mode
32 | }
33 |
34 | function press(keycode) {
35 | Quickshell.execDetached(["bash", "-c", `ydotool key --key-delay 0 ${keycode}:1`]);
36 | }
37 |
38 | function release(keycode) {
39 | Quickshell.execDetached(["bash", "-c", `ydotool key --key-delay 0 ${keycode}:0`]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/share/sleex/services/ai/AiMessageData.qml:
--------------------------------------------------------------------------------
1 | import QtQuick;
2 |
3 | /**
4 | * Represents a message in an AI conversation. (Kind of) follows the OpenAI API message structure.
5 | */
6 | QtObject {
7 | property string role
8 | property string content
9 | property string rawContent
10 | property string fileMimeType
11 | property string fileUri
12 | property string localFilePath
13 | property string model
14 | property bool thinking: true
15 | property bool done: false
16 | property var annotations: []
17 | property var annotationSources: []
18 | property list searchQueries: []
19 | property string functionName
20 | property var functionCall
21 | property string functionResponse
22 | property bool functionPending: false
23 | property bool visibleToUser: true
24 | }
25 |
--------------------------------------------------------------------------------
/src/share/sleex/services/ai/AiModel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick;
2 |
3 | /**
4 | * An AI model representation.
5 | * - name: Friendly name of the model
6 | * - icon: Icon name of the model
7 | * - description: Description of the model
8 | * - endpoint: Endpoint of the model
9 | * - model: Model code (like gpt-4.1 or gemini-2.5-flash)
10 | * - requires_key: Whether the model requires an API key
11 | * - key_id: The identifier of the API key. Use the same identifier for models that can be accessed with the same key.
12 | * - key_get_link: Link to get an API key
13 | * - key_get_description: Description of pricing and how to get an API key
14 | * - api_format: The API format of the model. Can be "openai" or "gemini". Default is "openai".
15 | * - extraParams: Extra parameters to be passed to the model. This is a JSON object.
16 | */
17 |
18 | QtObject {
19 | property string name
20 | property string icon
21 | property string description
22 | property string homepage
23 | property string endpoint
24 | property string model
25 | property bool requires_key: true
26 | property string key_id
27 | property string key_get_link
28 | property string key_get_description
29 | property string api_format: "openai"
30 | property var tools
31 | property var extraParams: ({})
32 | }
33 |
--------------------------------------------------------------------------------
/src/share/sleex/services/ai/ApiStrategy.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 |
3 | QtObject {
4 | function buildEndpoint(model: AiModel): string { throw new Error("Not implemented") }
5 | function buildRequestData(model: AiModel, messages, systemPrompt: string, temperature: real, tools: list, filePath: string) { throw new Error("Not implemented") }
6 | function buildAuthorizationHeader(apiKeyEnvVarName: string): string { throw new Error("Not implemented") }
7 | function parseResponseLine(line: string, message: AiMessageData) { throw new Error("Not implemented") }
8 | function onRequestFinished(message: AiMessageData): var { return {} } // Default: no special handling
9 | function reset() { } // Reset any internal state if needed
10 | function buildScriptFileSetup(filePath) { return "" } // Default: no setup
11 | function finalizeScriptContent(scriptContent: string): string { return scriptContent } // Optionally modify/finalize script
12 | }
13 |
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/Glooe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/Glooe.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/Gloow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/Gloow.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/RenderBall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/RenderBall.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/Robohand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/Robohand.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexBlackSE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexBlackSE.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexFour.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexFour.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexFourB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexFourB.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexFourSE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexFourSE.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexOne.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexOne.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexThree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexThree.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexThreeSE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexThreeSE.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexTwo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexTwo.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/SleexTwoSE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/SleexTwoSE.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/sakura.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/sakura.png
--------------------------------------------------------------------------------
/src/share/sleex/wallpapers/skyline.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AxOS-project/Sleex/a5dbc03abf47ff415d292bfbcdcbdec9fbb49077/src/share/sleex/wallpapers/skyline.jpg
--------------------------------------------------------------------------------
/src/share/wayland-sessions/sleex.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Sleex
3 | Comment=AxOS's third desktop environment
4 | Exec=sleex
5 | Icon=
6 | Type=Application
--------------------------------------------------------------------------------