Merge branch 'end-4:main' into fix/workflow-run-on-forks
@@ -2,22 +2,33 @@
|
||||
|
||||
- Please, please, please, make multiple PRs if you have many features/fixes, and don't shove your personal changes along with the PR, including changed defaults
|
||||
- We can accept features that we do not personally want, but in that case we will ask you to make it configurable/optionally loaded.
|
||||
- If you want to start working on something big to contribute, it might be a good idea to ask first to not waste your effort (but if you've already done it for yourself, it doesn't hurt to submit).
|
||||
- If you want to start working on something _big_ to contribute, it might be a good idea to ask first to not waste your effort (but if you've already done it for yourself, it doesn't hurt to submit).
|
||||
|
||||
# Code details
|
||||
# Translations
|
||||
|
||||
## Contributing to i18n
|
||||
See `dots/.config/quickshell/ii/translations/tools`
|
||||
|
||||
For contributing in translation (i18n) for Quickshell, see also `dots/.config/quickshell/ii/translations/tools`.
|
||||
# Code
|
||||
|
||||
## Dynamic loading
|
||||
|
||||
- If something's not always necessary, especially when guarded by a config option to enable/disable, put it in a `Loader`. One tip with `Loader`s is sometimes you will need to declare positioning properties (like `anchors`) in the `Loader`, not the `sourceComponent`.
|
||||
- If something's not always necessary, especially when guarded by a config option to enable/disable, put it in a `Loader`
|
||||
- Note that you will need to declare positioning properties (like `anchors`) in the `Loader`, not the `sourceComponent`
|
||||
- When something that's to be dynamically loaded doesn't affect its parent layout, you can have a fading animation by using FadeLoader and set the `shown` prop instead of `active` and `visible`
|
||||
|
||||
## Practical concerns
|
||||
|
||||
- Make sure what you add does not require significant resources for a minor purpose or harm usability just for the sake of looking nice. The dotfiles must remain practical for daily driving.
|
||||
- If there is something really fancy and impractical anyway, add a config option for it and make sure it's disabled by default.
|
||||
- If there is something really fancy and impractical anyway, add a config option for it and make sure it's disabled by default (example: constantly rotating background clock)
|
||||
|
||||
## Style
|
||||
|
||||
- Spaces
|
||||
- Space properties and children data into meaningful groups. (but of course, don't use 2+ blanks in a row)
|
||||
- Put spaces between text and operators: `if (condition) { ... } else { ... }` instead of `if(condition){ ... }else{ ... }`
|
||||
- As you can see, it's pretty easy to use lots of nesting. There's no hard limit, end-4 himself nests a lot too, but avoid/mitigate that:
|
||||
- Prefer early return: Use something like `if (!condition) return; doStuff();` instead of `if (condition) { doStuff() }`
|
||||
- If you feel it's a bother to refractor something into a new file, remember there's `component` to declare reusable components in the same file.
|
||||
|
||||
# Setting up
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ Widget system: Quickshell | Support: Yes
|
||||
|:---|:---------------|
|
||||
| <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/ea0154a1-e984-4bb6-a424-23247cefe3c6" /> | <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/6eba0d57-2606-4cea-8993-e6f169e82e70" /> |
|
||||
| Window management | Weeb power |
|
||||
| <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/e77a7c96-1905-4126-a2a0-434f818825a2" /> | <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/c8544e99-8881-477f-b83a-d6e35c0184a1" /> |
|
||||
| <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/a7e6d29c-e82c-4934-98db-36c810ec999b" /> | <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/c8544e99-8881-477f-b83a-d6e35c0184a1" /> |
|
||||
|
||||
### Other styles: Available at the end of the readme.
|
||||
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
/diagnose.result
|
||||
/cache
|
||||
|
||||
# Ignore Python cache files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
dots/.config/quickshell/ii/.qmlls.ini
|
||||
.update-lock
|
||||
|
||||
/dots/.config/quickshell/ii/.qmlls.ini
|
||||
|
||||
# exp-update
|
||||
/.update-lock
|
||||
|
||||
# custom os-release
|
||||
/os-release
|
||||
#emacs backup
|
||||
|
||||
# Emacs auto backup file
|
||||
*~
|
||||
|
||||
@@ -70,6 +70,7 @@ x git submodule status --recursive
|
||||
|
||||
e "Checking distro"
|
||||
x _check_distro_id
|
||||
x cat os-release
|
||||
#x _check_distro
|
||||
|
||||
e "Checking variables"
|
||||
|
||||
@@ -14,7 +14,7 @@ exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISP
|
||||
exec-once = hyprpm reload
|
||||
|
||||
# Audio
|
||||
exec-once = easyeffects --gapplication-service
|
||||
exec-once = easyeffects --hide-window --service-mode
|
||||
|
||||
# Clipboard: history
|
||||
# exec-once = wl-paste --watch cliphist store &
|
||||
|
||||
@@ -24,8 +24,8 @@ bindit = ,Super_L, global, quickshell:workspaceNumber # [hidden]
|
||||
bindit = ,Super_R, global, quickshell:workspaceNumber # [hidden]
|
||||
bindd = Super, V, Clipboard history >> clipboard, global, quickshell:overviewClipboardToggle # Clipboard history >> clipboard
|
||||
bindd = Super, Period, Emoji >> clipboard, global, quickshell:overviewEmojiToggle # Emoji >> clipboard
|
||||
bindd = Super, Tab, Toggle overview, global, quickshell:overviewToggle # [hidden] Toggle overview/launcher (alt)
|
||||
bindd = Super, A, Toggle left sidebar, global, quickshell:sidebarLeftToggle # Toggle left sidebar
|
||||
bind = Super, Tab, global, quickshell:overviewWorkspacesToggle # [hidden] Toggle overview/launcher (alt)
|
||||
bind = Super, A, global, quickshell:sidebarLeftToggle # Toggle left sidebar
|
||||
bind = Super+Alt, A, global, quickshell:sidebarLeftToggleDetach # [hidden]
|
||||
bind = Super, B, global, quickshell:sidebarLeftToggle # [hidden]
|
||||
bind = Super, O, global, quickshell:sidebarLeftToggle # [hidden]
|
||||
|
||||
@@ -133,12 +133,14 @@ layerrule = blurpopups, quickshell:.*
|
||||
layerrule = blur, quickshell:.*
|
||||
layerrule = ignorealpha 0.79, quickshell:.*
|
||||
layerrule = animation slide, quickshell:bar
|
||||
layerrule = noanim, quickshell:actionCenter
|
||||
layerrule = animation slide bottom, quickshell:cheatsheet
|
||||
layerrule = animation slide bottom, quickshell:dock
|
||||
layerrule = animation popin 120%, quickshell:screenCorners
|
||||
layerrule = noanim, quickshell:lockWindowPusher
|
||||
layerrule = animation fade, quickshell:notificationPopup
|
||||
layerrule = noanim, quickshell:overlay
|
||||
layerrule = ignorealpha 1, quickshell:overlay
|
||||
layerrule = noanim, quickshell:overview
|
||||
layerrule = animation slide bottom, quickshell:osk
|
||||
layerrule = noanim, quickshell:polkit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
The "search" and "task view" icons are from here, with modifications
|
||||
The "start-here", "search" and "task view" icons are from here, with modifications
|
||||
|
||||
https://www.figma.com/community/file/1123040825921884189/windows-11
|
||||
[Windows 11 by Joshua Oghenekaro Okwe - Figma](https://www.figma.com/community/file/1123040825921884189/windows-11)
|
||||
|
||||
License: CC BY 4.0
|
||||
License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.en)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="arrow-sync.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="25.868323"
|
||||
inkscape:cx="14.245222"
|
||||
inkscape:cy="12.447657"
|
||||
inkscape:window-width="1498"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<path
|
||||
d="m 19.947024,13.17933 a 0.75,0.75 0 0 0 -0.907212,0.549312 7.251,7.251 0 0 1 -13.334866,1.873667 l 0.8908023,0.350894 a 0.75,0.75 0 0 0 0.6494514,-1.347747 l -0.100442,-0.04793 -2.6316174,-1.036623 a 0.75,0.75 0 0 0 -0.9241627,0.322228 l -0.047921,0.100457 -1.0366214,2.631619 a 0.75,0.75 0 0 0 1.3468323,0.649854 l 0.048321,-0.09951 0.3887326,-0.986859 A 8.75,8.75 0 0 0 20.494492,14.087329 0.75,0.75 0 0 0 19.946102,13.179722 Z M 21.068469,6.4543893 A 0.75,0.75 0 0 0 20.096388,6.8770607 L 19.707652,7.863919 A 8.75,8.75 0 0 0 3.5868012,9.5848274 0.75043107,0.75043107 0 1 0 5.0290446,10.000183 7.251,7.251 0 0 1 18.290631,8.3993655 l -0.8904,-0.3499798 a 0.75,0.75 0 1 0 -0.549014,1.3956769 l 2.631617,1.0366214 a 0.75,0.75 0 0 0 0.972088,-0.422667 L 21.491544,7.4273949 A 0.75,0.75 0 0 0 21.068874,6.455308 Z"
|
||||
fill="#212121"
|
||||
id="path1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1 @@
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414Z" fill="#212121"/></svg>
|
||||
|
After Width: | Height: | Size: 249 B |
@@ -0,0 +1 @@
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3.28 2.22a.75.75 0 0 0-1.06 1.06l5.905 5.905L4.81 10.33a1.25 1.25 0 0 0-.476 2.065L7.439 15.5 3 19.94V21h1.06l4.44-4.44 3.105 3.105a1.25 1.25 0 0 0 2.065-.476l1.145-3.313 5.905 5.904a.75.75 0 0 0 1.06-1.06L3.28 2.22Zm10.355 12.476-1.252 3.626-6.705-6.705 3.626-1.252 4.331 4.331Zm6.048-3.876-3.787 1.894 1.118 1.118 3.34-1.67a2.75 2.75 0 0 0 .714-4.404l-4.825-4.826a2.75 2.75 0 0 0-4.405.715l-1.67 3.34 1.118 1.117 1.894-3.787a1.25 1.25 0 0 1 2.002-.325l4.826 4.826a1.25 1.25 0 0 1-.325 2.002Z" fill="#212121"/></svg>
|
||||
|
After Width: | Height: | Size: 622 B |
@@ -0,0 +1 @@
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m16.242 2.932 4.826 4.826a2.75 2.75 0 0 1-.715 4.404l-4.87 2.435a.75.75 0 0 0-.374.426l-1.44 4.166a1.25 1.25 0 0 1-2.065.476L8.5 16.561 4.06 21H3v-1.06l4.44-4.44-3.105-3.104a1.25 1.25 0 0 1 .476-2.066l4.166-1.44a.75.75 0 0 0 .426-.373l2.435-4.87a2.75 2.75 0 0 1 4.405-.715Zm3.766 5.886-4.826-4.826a1.25 1.25 0 0 0-2.002.325l-2.435 4.871a2.25 2.25 0 0 1-1.278 1.12l-3.789 1.31 6.705 6.704 1.308-3.789a2.25 2.25 0 0 1 1.12-1.277l4.872-2.436a1.25 1.25 0 0 0 .325-2.002Z" fill="#212121"/></svg>
|
||||
|
After Width: | Height: | Size: 594 B |
@@ -0,0 +1 @@
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.012 2.25c.734.008 1.465.093 2.182.253a.75.75 0 0 1 .582.649l.17 1.527a1.384 1.384 0 0 0 1.927 1.116l1.401-.615a.75.75 0 0 1 .85.174 9.792 9.792 0 0 1 2.204 3.792.75.75 0 0 1-.271.825l-1.242.916a1.381 1.381 0 0 0 0 2.226l1.243.915a.75.75 0 0 1 .272.826 9.797 9.797 0 0 1-2.204 3.792.75.75 0 0 1-.848.175l-1.407-.617a1.38 1.38 0 0 0-1.926 1.114l-.169 1.526a.75.75 0 0 1-.572.647 9.518 9.518 0 0 1-4.406 0 .75.75 0 0 1-.572-.647l-.168-1.524a1.382 1.382 0 0 0-1.926-1.11l-1.406.616a.75.75 0 0 1-.849-.175 9.798 9.798 0 0 1-2.204-3.796.75.75 0 0 1 .272-.826l1.243-.916a1.38 1.38 0 0 0 0-2.226l-1.243-.914a.75.75 0 0 1-.271-.826 9.793 9.793 0 0 1 2.204-3.792.75.75 0 0 1 .85-.174l1.4.615a1.387 1.387 0 0 0 1.93-1.118l.17-1.526a.75.75 0 0 1 .583-.65c.717-.159 1.45-.243 2.201-.252Zm0 1.5a9.135 9.135 0 0 0-1.354.117l-.109.977A2.886 2.886 0 0 1 6.525 7.17l-.898-.394a8.293 8.293 0 0 0-1.348 2.317l.798.587a2.881 2.881 0 0 1 0 4.643l-.799.588c.32.842.776 1.626 1.348 2.322l.905-.397a2.882 2.882 0 0 1 4.017 2.318l.11.984c.889.15 1.798.15 2.687 0l.11-.984a2.881 2.881 0 0 1 4.018-2.322l.905.396a8.296 8.296 0 0 0 1.347-2.318l-.798-.588a2.881 2.881 0 0 1 0-4.643l.796-.587a8.293 8.293 0 0 0-1.348-2.317l-.896.393a2.884 2.884 0 0 1-4.023-2.324l-.11-.976a8.988 8.988 0 0 0-1.333-.117ZM12 8.25a3.75 3.75 0 1 1 0 7.5 3.75 3.75 0 0 1 0-7.5Zm0 1.5a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5Z" fill="#212121"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,24 @@
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 6.2C4 4.98497 4.98497 4 6.2 4H28.2C29.415 4 30.4 4.98497 30.4 6.2V28.2C30.4 29.415 29.415 30.4 28.2 30.4H6.2C4.98497 30.4 4 29.415 4 28.2V6.2Z" fill="url(#paint0_radial_520_19)"/>
|
||||
<path d="M32.6 6.2C32.6 4.98497 33.585 4 34.8 4H56.8C58.015 4 59 4.98497 59 6.2V28.2C59 29.415 58.015 30.4 56.8 30.4H34.8C33.585 30.4 32.6 29.415 32.6 28.2V6.2Z" fill="url(#paint1_radial_520_19)"/>
|
||||
<path d="M32.6 34.8C32.6 33.585 33.585 32.6 34.8 32.6H56.8C58.015 32.6 59 33.585 59 34.8V56.8C59 58.015 58.015 59 56.8 59H34.8C33.585 59 32.6 58.015 32.6 56.8V34.8Z" fill="url(#paint2_radial_520_19)"/>
|
||||
<path d="M4 34.8C4 33.585 4.98497 32.6 6.2 32.6H28.2C29.415 32.6 30.4 33.585 30.4 34.8V56.8C30.4 58.015 29.415 59 28.2 59H6.2C4.98497 59 4 58.015 4 56.8V34.8Z" fill="url(#paint3_radial_520_19)"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_520_19" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#0B9BFE"/>
|
||||
<stop offset="1" stop-color="#0B9BFE"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint1_radial_520_19" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#0B9BFE"/>
|
||||
<stop offset="1" stop-color="#0B9BFE"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint2_radial_520_19" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#0B9BFE"/>
|
||||
<stop offset="1" stop-color="#0B9BFE"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint3_radial_520_19" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#0B9BFE"/>
|
||||
<stop offset="1" stop-color="#0B9BFE"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,24 @@
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 6.2C4 4.98497 4.98497 4 6.2 4H28.2C29.415 4 30.4 4.98497 30.4 6.2V28.2C30.4 29.415 29.415 30.4 28.2 30.4H6.2C4.98497 30.4 4 29.415 4 28.2V6.2Z" fill="url(#paint0_radial_519_6)"/>
|
||||
<path d="M32.6 6.2C32.6 4.98497 33.585 4 34.8 4H56.8C58.015 4 59 4.98497 59 6.2V28.2C59 29.415 58.015 30.4 56.8 30.4H34.8C33.585 30.4 32.6 29.415 32.6 28.2V6.2Z" fill="url(#paint1_radial_519_6)"/>
|
||||
<path d="M32.6 34.8C32.6 33.585 33.585 32.6 34.8 32.6H56.8C58.015 32.6 59 33.585 59 34.8V56.8C59 58.015 58.015 59 56.8 59H34.8C33.585 59 32.6 58.015 32.6 56.8V34.8Z" fill="url(#paint2_radial_519_6)"/>
|
||||
<path d="M4 34.8C4 33.585 4.98497 32.6 6.2 32.6H28.2C29.415 32.6 30.4 33.585 30.4 34.8V56.8C30.4 58.015 29.415 59 28.2 59H6.2C4.98497 59 4 58.015 4 56.8V34.8Z" fill="url(#paint3_radial_519_6)"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_519_6" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#81DFFF"/>
|
||||
<stop offset="1" stop-color="#0A99F9"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint1_radial_519_6" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#81DFFF"/>
|
||||
<stop offset="1" stop-color="#0A99F9"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint2_radial_519_6" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#81DFFF"/>
|
||||
<stop offset="1" stop-color="#0A99F9"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint3_radial_519_6" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(45) scale(77.7817)">
|
||||
<stop stop-color="#81DFFF"/>
|
||||
<stop offset="1" stop-color="#0A99F9"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
version="1.1"
|
||||
viewBox="0 0 16.933 16.933"
|
||||
id="svg2"
|
||||
sodipodi:docname="system-search-checked-dark.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview2"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="4.65625"
|
||||
inkscape:cx="32"
|
||||
inkscape:cy="32"
|
||||
inkscape:window-width="1197"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g2" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#565757;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3" />
|
||||
<stop
|
||||
style="stop-color:#4c4f52;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient919"
|
||||
x1="4.3106"
|
||||
x2="14.36"
|
||||
y1="8.4665"
|
||||
y2="8.4665"
|
||||
gradientTransform="matrix(1.226575,0,0,1.226575,-0.82407803,-6.4497629)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#3c8cff"
|
||||
offset="0"
|
||||
id="stop1"
|
||||
style="stop-color:#5fe277;stop-opacity:1;" />
|
||||
<stop
|
||||
stop-color="#55b4ff"
|
||||
offset="1"
|
||||
id="stop2"
|
||||
style="stop-color:#0078d3;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="linearGradient4"
|
||||
x1="-7.2925777"
|
||||
y1="11.283"
|
||||
x2="5.189723"
|
||||
y2="11.283"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(11.677839,-7.3471437)" />
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(16.148 .19097)"
|
||||
id="g2">
|
||||
<rect
|
||||
transform="rotate(45)"
|
||||
x="2.891"
|
||||
y="10.492"
|
||||
width="7.4901"
|
||||
height="1.583"
|
||||
ry=".79147"
|
||||
fill="#1955b9"
|
||||
stroke-width="1.1651"
|
||||
id="rect2"
|
||||
style="stroke-width:1.16520206;stroke-dasharray:none;fill:#0175d1;fill-opacity:1" />
|
||||
<circle
|
||||
transform="rotate(120)"
|
||||
cx="10.62641"
|
||||
cy="3.9358561"
|
||||
r="5.3520403"
|
||||
fill="none"
|
||||
stroke="url(#linearGradient919)"
|
||||
stroke-linecap="round"
|
||||
stroke-width="1.77822"
|
||||
id="circle2"
|
||||
style="fill:url(#linearGradient4);stroke:url(#linearGradient919);stroke-width:1.77822958;stroke-dasharray:none" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
version="1.1"
|
||||
viewBox="0 0 16.933 16.933"
|
||||
id="svg2"
|
||||
sodipodi:docname="system-search-checked-light.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview2"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="6.5849319"
|
||||
inkscape:cx="26.95548"
|
||||
inkscape:cy="26.423963"
|
||||
inkscape:window-width="1257"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient919"
|
||||
x1="4.3106"
|
||||
x2="14.36"
|
||||
y1="8.4665"
|
||||
y2="8.4665"
|
||||
gradientTransform="matrix(1.226575,0,0,1.226575,-0.82407803,-6.4497629)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#3c8cff"
|
||||
offset="0"
|
||||
id="stop1"
|
||||
style="stop-color:#5fe277;stop-opacity:1;" />
|
||||
<stop
|
||||
stop-color="#55b4ff"
|
||||
offset="1"
|
||||
id="stop2"
|
||||
style="stop-color:#0078d3;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect
|
||||
transform="rotate(45,7.8434785,19.587845)"
|
||||
x="3.4592254"
|
||||
y="10.492"
|
||||
width="6.921874"
|
||||
height="1.5830002"
|
||||
ry="0.71336967"
|
||||
fill="#1955b9"
|
||||
stroke-width="1.1651"
|
||||
id="rect2-5"
|
||||
style="fill:#0077d4;fill-opacity:1;stroke-width:1.1652;stroke-dasharray:none" />
|
||||
<circle
|
||||
transform="rotate(120,8.0188717,4.757011)"
|
||||
cx="10.62641"
|
||||
cy="3.9358561"
|
||||
r="5.3520403"
|
||||
fill="none"
|
||||
stroke="url(#linearGradient919)"
|
||||
stroke-linecap="round"
|
||||
stroke-width="1.77822"
|
||||
id="circle2"
|
||||
style="fill:none;stroke:url(#linearGradient919);stroke-width:1.77822958;stroke-dasharray:none" />
|
||||
<g
|
||||
transform="translate(16.148 .19097)"
|
||||
id="g2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -7,10 +7,11 @@
|
||||
version="1.1"
|
||||
viewBox="0 0 16.933 16.933"
|
||||
id="svg2"
|
||||
sodipodi:docname="system-search.svg"
|
||||
sodipodi:docname="system-search-dark.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
@@ -24,15 +25,27 @@
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="4.65625"
|
||||
inkscape:cx="32"
|
||||
inkscape:cy="32"
|
||||
inkscape:cy="31.892617"
|
||||
inkscape:window-width="1061"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-height="835"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g2" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#565757;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3" />
|
||||
<stop
|
||||
style="stop-color:#4c4f52;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient919"
|
||||
x1="4.3106"
|
||||
@@ -52,6 +65,15 @@
|
||||
id="stop2"
|
||||
style="stop-color:#d7dcdf;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="linearGradient4"
|
||||
x1="-7.2925777"
|
||||
y1="11.283"
|
||||
x2="5.189723"
|
||||
y2="11.283"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(16.148 .19097)"
|
||||
@@ -77,6 +99,6 @@
|
||||
stroke-linecap="round"
|
||||
stroke-width="1.77822"
|
||||
id="circle2"
|
||||
style="fill:#4f4f4f;fill-opacity:1;stroke:url(#linearGradient919)" />
|
||||
style="fill:url(#linearGradient4);fill-opacity:1;stroke:url(#linearGradient919)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="63.999989"
|
||||
height="61.62962"
|
||||
viewBox="0 0 26.999999 26"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="task-view-dark-pressed.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="6.0349946"
|
||||
inkscape:cx="32.228695"
|
||||
inkscape:cy="33.305746"
|
||||
inkscape:window-width="1331"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g3" />
|
||||
<g
|
||||
id="g3"
|
||||
transform="translate(0.03879728,0.03736111)">
|
||||
<g
|
||||
id="g4"
|
||||
transform="translate(-1.6875003,2.5312505)">
|
||||
<rect
|
||||
opacity="0.9"
|
||||
x="9.4441719"
|
||||
width="17.938911"
|
||||
height="15.248073"
|
||||
rx="0.89694548"
|
||||
fill="#ffffff"
|
||||
id="rect1"
|
||||
y="0.8962484"
|
||||
style="fill:url(#linearGradient4);fill-opacity:1;stroke:#e2e2e2;stroke-width:0.179719;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="translate(-2.3652457,0.93944352)" />
|
||||
<rect
|
||||
y="3.8563478"
|
||||
width="17.953642"
|
||||
height="15.260596"
|
||||
rx="0.89768213"
|
||||
fill="url(#paint0_linear_505_17)"
|
||||
id="rect2"
|
||||
x="5.1897082"
|
||||
style="mix-blend-mode:exclusion;fill:url(#paint0_linear_505_17-3);stroke-width:0.89775;stroke-dasharray:none" />
|
||||
</g>
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-2.3652457,0.93944351)">
|
||||
<g
|
||||
style="mix-blend-mode:exclusion;stroke-width:1.00007574;stroke-dasharray:none"
|
||||
id="g2"
|
||||
transform="matrix(0.89768215,0,0,0.89768215,4.1799533,-0.09973431)" />
|
||||
</g>
|
||||
</g>
|
||||
<defs
|
||||
id="defs3">
|
||||
<linearGradient
|
||||
id="paint0_linear_505_17"
|
||||
x1="-2.75374e-08"
|
||||
y1="9.2399397"
|
||||
x2="18.808399"
|
||||
y2="26.838499"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#717171"
|
||||
id="stop2"
|
||||
offset="0"
|
||||
style="stop-color:#717171;stop-opacity:0.73333335;" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#4F4F4F"
|
||||
id="stop3"
|
||||
style="stop-color:#4f4f4f;stop-opacity:0.73333335;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint0_linear_505_17-3"
|
||||
x1="-2.75374e-08"
|
||||
y1="9.2399397"
|
||||
x2="18.808399"
|
||||
y2="26.838499"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.89768213,0,0,0.89768213,5.189708,-4.2227915)">
|
||||
<stop
|
||||
stop-color="#717171"
|
||||
id="stop2-6"
|
||||
offset="0"
|
||||
style="stop-color:#717171;stop-opacity:0.60000002;" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#4F4F4F"
|
||||
id="stop3-7"
|
||||
style="stop-color:#565656;stop-opacity:0.60000002;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="linearGradient4"
|
||||
x1="7.1907158"
|
||||
y1="8.3216944"
|
||||
x2="24.995911"
|
||||
y2="10.507897"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(2.3203156,-0.89451377)" />
|
||||
<linearGradient
|
||||
id="linearGradient1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop1" />
|
||||
<stop
|
||||
style="stop-color:#e6e6e6;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="63.999989"
|
||||
height="61.62962"
|
||||
viewBox="0 0 26.999999 26"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="task-view-checked-light.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="4.7640337"
|
||||
inkscape:cx="21.200522"
|
||||
inkscape:cy="37.573202"
|
||||
inkscape:window-width="1238"
|
||||
inkscape:window-height="612"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g3" />
|
||||
<g
|
||||
id="g3"
|
||||
transform="translate(0.03879728,0.03736111)">
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-1.7324301,2.5761801)">
|
||||
<g
|
||||
style="mix-blend-mode:exclusion;stroke-width:0.999982;stroke-dasharray:none"
|
||||
id="g2"
|
||||
transform="matrix(0.89768215,0,0,0.89768215,5.2346381,-4.2677212)">
|
||||
<rect
|
||||
y="9"
|
||||
width="20"
|
||||
height="17"
|
||||
rx="1"
|
||||
fill="url(#paint0_linear_505_17)"
|
||||
id="rect2"
|
||||
x="0"
|
||||
style="fill:url(#paint0_linear_505_17);stroke-width:0.999982;stroke-dasharray:none" />
|
||||
</g>
|
||||
<rect
|
||||
opacity="0.9"
|
||||
x="7.1238561"
|
||||
width="17.938911"
|
||||
height="15.248073"
|
||||
rx="0.89694548"
|
||||
fill="#ffffff"
|
||||
id="rect1"
|
||||
y="1.7907622"
|
||||
style="fill:url(#linearGradient4);fill-opacity:1;stroke:#d4d4d4;stroke-width:0.179719;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<defs
|
||||
id="defs3">
|
||||
<linearGradient
|
||||
id="linearGradient1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.80000001;"
|
||||
offset="0"
|
||||
id="stop1" />
|
||||
<stop
|
||||
style="stop-color:#e6e6e6;stop-opacity:0.80000001;"
|
||||
offset="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint0_linear_505_17"
|
||||
x1="-2.75374e-08"
|
||||
y1="9.2399397"
|
||||
x2="18.808399"
|
||||
y2="26.838499"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#717171"
|
||||
id="stop2"
|
||||
offset="0"
|
||||
style="stop-color:#464543;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#4F4F4F"
|
||||
id="stop3"
|
||||
style="stop-color:#1f1f1f;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="linearGradient4"
|
||||
x1="7.1729918"
|
||||
y1="8.4772339"
|
||||
x2="25.013634"
|
||||
y2="10.352362"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.modules.common.functions
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
@@ -147,6 +148,7 @@ Singleton {
|
||||
property string networkEthernet: "kcmshell6 kcm_networkmanagement"
|
||||
property string taskManager: "plasma-systemmonitor --page-name Processes"
|
||||
property string terminal: "kitty -1" // This is only for shell actions
|
||||
property string update: "kitty -1 --hold=yes fish -i -c 'sudo pacman -Syu'"
|
||||
property string volumeMixer: `~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol"`
|
||||
}
|
||||
|
||||
@@ -158,7 +160,8 @@ Singleton {
|
||||
property string placementStrategy: "leastBusy" // "free", "leastBusy", "mostBusy"
|
||||
property real x: 100
|
||||
property real y: 100
|
||||
property string style: "cookie" // Options: "cookie", "digital"
|
||||
property string style: "cookie" // Options: "cookie", "digital"
|
||||
property string styleLocked: "cookie" // Options: "cookie", "digital"
|
||||
property JsonObject cookie: JsonObject {
|
||||
property bool aiStyling: false
|
||||
property int sides: 14
|
||||
@@ -236,13 +239,6 @@ Singleton {
|
||||
property bool showPerformanceProfileToggle: false
|
||||
property bool showScreenRecord: false
|
||||
}
|
||||
property JsonObject tray: JsonObject {
|
||||
property bool monochromeIcons: true
|
||||
property bool showItemId: false
|
||||
property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area
|
||||
property list<string> pinnedItems: [ ]
|
||||
property bool filterPassive: true
|
||||
}
|
||||
property JsonObject workspaces: JsonObject {
|
||||
property bool monochromeIcons: true
|
||||
property int shown: 10
|
||||
@@ -264,6 +260,9 @@ Singleton {
|
||||
property bool showUnreadCount: false
|
||||
}
|
||||
}
|
||||
property JsonObject tooltips: JsonObject {
|
||||
property bool clickToShow: false
|
||||
}
|
||||
}
|
||||
|
||||
property JsonObject battery: JsonObject {
|
||||
@@ -426,6 +425,14 @@ Singleton {
|
||||
property int historyLength: 60
|
||||
}
|
||||
|
||||
property JsonObject tray: JsonObject {
|
||||
property bool monochromeIcons: true
|
||||
property bool showItemId: false
|
||||
property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area
|
||||
property list<var> pinnedItems: [ "Fcitx" ]
|
||||
property bool filterPassive: true
|
||||
}
|
||||
|
||||
property JsonObject musicRecognition: JsonObject {
|
||||
property int timeout: 16
|
||||
property int interval: 4
|
||||
@@ -533,6 +540,12 @@ Singleton {
|
||||
property bool secondPrecision: false
|
||||
}
|
||||
|
||||
property JsonObject updates: JsonObject {
|
||||
property int checkInterval: 120 // minutes
|
||||
property int adviseUpdateThreshold: 75 // packages
|
||||
property int stronglyAdviseUpdateThreshold: 200 // packages
|
||||
}
|
||||
|
||||
property JsonObject wallpaperSelector: JsonObject {
|
||||
property bool useSystemFileDialog: false
|
||||
}
|
||||
@@ -559,6 +572,10 @@ Singleton {
|
||||
}
|
||||
|
||||
property JsonObject waffles: JsonObject {
|
||||
// Animations on Windoes are kinda janky. Set the following to
|
||||
// false will make (some) stuff also be like that for accuracy.
|
||||
// Example: the right-click menu of the Start button
|
||||
property bool smootherAnimations: true
|
||||
property JsonObject bar: JsonObject {
|
||||
property bool bottom: true
|
||||
property bool leftAlignApps: false
|
||||
|
||||
@@ -32,7 +32,9 @@ Singleton {
|
||||
property string shellConfig: FileUtils.trimFileProtocol(`${Directories.config}/illogical-impulse`)
|
||||
property string shellConfigName: "config.json"
|
||||
property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}`
|
||||
property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`)
|
||||
property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`)
|
||||
property string notesPath: FileUtils.trimFileProtocol(`${Directories.state}/user/notes.txt`)
|
||||
property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`)
|
||||
property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`)
|
||||
property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`)
|
||||
property string generatedWallpaperCategoryPath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/wallpaper/category.txt`)
|
||||
|
||||
@@ -131,6 +131,14 @@ Singleton {
|
||||
property real height: 600
|
||||
property int tabIndex: 0
|
||||
}
|
||||
property JsonObject notes: JsonObject {
|
||||
property bool pinned: false
|
||||
property bool clickthrough: true
|
||||
property real x: 1400
|
||||
property real y: 42
|
||||
property real width: 460
|
||||
property real height: 330
|
||||
}
|
||||
}
|
||||
|
||||
property JsonObject timer: JsonObject {
|
||||
|
||||
@@ -285,4 +285,14 @@ Singleton {
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function toTitleCase(str) {
|
||||
// Replace "-" and "_" with space, then capitalize each word
|
||||
return str.replace(/[-_]/g, " ").replace(
|
||||
/\w\S*/g,
|
||||
function(txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@ import qs.modules.common.widgets
|
||||
Loader {
|
||||
id: root
|
||||
property bool shown: true
|
||||
property alias fade: opacityBehavior.enabled
|
||||
opacity: shown ? 1 : 0
|
||||
visible: opacity > 0
|
||||
active: opacity > 0
|
||||
|
||||
Behavior on opacity {
|
||||
id: opacityBehavior
|
||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ StyledListView { // Scrollable window
|
||||
required property int index
|
||||
required property var modelData
|
||||
popup: root.popup
|
||||
anchors.left: parent?.left
|
||||
anchors.right: parent?.right
|
||||
width: ListView.view.width // https://doc.qt.io/qt-6/qml-qtquick-listview.html
|
||||
notificationGroup: popup ?
|
||||
Notifications.popupGroupsByAppName[modelData] :
|
||||
Notifications.groupsByAppName[modelData]
|
||||
|
||||
@@ -14,6 +14,10 @@ Item {
|
||||
property real horizontalPadding: 10
|
||||
property real verticalPadding: 5
|
||||
|
||||
function updateAnchor() {
|
||||
tooltipLoader.item?.anchor.updateAnchor();
|
||||
}
|
||||
|
||||
readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition
|
||||
property var anchorEdges: Edges.Top
|
||||
property var anchorGravity: anchorEdges
|
||||
|
||||
@@ -10,6 +10,7 @@ TextArea {
|
||||
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
|
||||
selectionColor: Appearance.colors.colSecondaryContainer
|
||||
placeholderTextColor: Appearance.m3colors.m3outline
|
||||
color: Appearance.colors.colOnLayer0
|
||||
font {
|
||||
family: Appearance.font.family.main
|
||||
pixelSize: Appearance?.font.pixelSize.small ?? 15
|
||||
|
||||
@@ -5,7 +5,6 @@ import qs.services
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt.labs.synchronizer
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
@@ -16,7 +16,7 @@ AbstractBackgroundWidget {
|
||||
implicitHeight: contentColumn.implicitHeight
|
||||
implicitWidth: contentColumn.implicitWidth
|
||||
|
||||
readonly property string clockStyle: Config.options.background.widgets.clock.style
|
||||
readonly property string clockStyle: GlobalStates.screenLocked ? Config.options.background.widgets.clock.styleLocked : Config.options.background.widgets.clock.style
|
||||
readonly property bool forceCenter: (GlobalStates.screenLocked && Config.options.lock.centerClock)
|
||||
readonly property bool shouldShow: (!Config.options.background.widgets.clock.showOnlyWhenLocked || GlobalStates.screenLocked)
|
||||
property bool wallpaperSafetyTriggered: false
|
||||
@@ -44,6 +44,7 @@ AbstractBackgroundWidget {
|
||||
id: cookieClockLoader
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
shown: root.clockStyle === "cookie" && (root.shouldShow)
|
||||
fade: false
|
||||
sourceComponent: Column {
|
||||
spacing: 10
|
||||
CookieClock {
|
||||
@@ -61,6 +62,7 @@ AbstractBackgroundWidget {
|
||||
id: digitalClockLoader
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
shown: root.clockStyle === "digital" && (root.shouldShow)
|
||||
fade: false
|
||||
sourceComponent: ColumnLayout {
|
||||
id: clockColumn
|
||||
spacing: 6
|
||||
|
||||
@@ -16,7 +16,7 @@ MouseArea {
|
||||
implicitWidth: batteryProgress.implicitWidth
|
||||
implicitHeight: Appearance.sizes.barHeight
|
||||
|
||||
hoverEnabled: true
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
|
||||
ClippedProgressBar {
|
||||
id: batteryProgress
|
||||
|
||||
@@ -40,8 +40,7 @@ Item {
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
|
||||
ClockWidgetPopup {
|
||||
hoverTarget: mouseArea
|
||||
|
||||
@@ -9,7 +9,7 @@ MouseArea {
|
||||
property bool alwaysShowAllResources: false
|
||||
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
|
||||
implicitHeight: Appearance.sizes.barHeight
|
||||
hoverEnabled: true
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
|
||||
RowLayout {
|
||||
id: rowLayout
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Services.SystemTray
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -17,13 +18,8 @@ Item {
|
||||
property bool showOverflowMenu: true
|
||||
property var activeMenu: null
|
||||
|
||||
property bool smartTray: Config.options.bar.tray.filterPassive
|
||||
property list<var> itemsInUserList: SystemTray.items.values.filter(i => (Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
|
||||
property list<var> itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
|
||||
|
||||
property bool invertPins: Config.options.bar.tray.invertPinnedItems
|
||||
property list<var> pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList
|
||||
property list<var> unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList
|
||||
property list<var> pinnedItems: TrayService.pinnedItems
|
||||
property list<var> unpinnedItems: TrayService.unpinnedItems
|
||||
onUnpinnedItemsChanged: {
|
||||
if (unpinnedItems.length == 0) root.closeOverflowMenu();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Services.SystemTray
|
||||
import Quickshell.Widgets
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
|
||||
MouseArea {
|
||||
id: root
|
||||
@@ -31,10 +32,7 @@ MouseArea {
|
||||
event.accepted = true;
|
||||
}
|
||||
onEntered: {
|
||||
tooltip.text = item.tooltipTitle.length > 0 ? item.tooltipTitle
|
||||
: (item.title.length > 0 ? item.title : item.id);
|
||||
if (item.tooltipDescription.length > 0) tooltip.text += " • " + item.tooltipDescription;
|
||||
if (Config.options.bar.tray.showItemId) tooltip.text += "\n[" + item.id + "]";
|
||||
tooltip.text = TrayService.getTooltipForItem(root.item);
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -65,7 +63,7 @@ MouseArea {
|
||||
|
||||
IconImage {
|
||||
id: trayIcon
|
||||
visible: !Config.options.bar.tray.monochromeIcons
|
||||
visible: !Config.options.tray.monochromeIcons
|
||||
source: root.item.icon
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
@@ -73,7 +71,7 @@ MouseArea {
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: Config.options.bar.tray.monochromeIcons
|
||||
active: Config.options.tray.monochromeIcons
|
||||
anchors.fill: trayIcon
|
||||
sourceComponent: Item {
|
||||
Desaturate {
|
||||
|
||||
@@ -13,15 +13,19 @@ MouseArea {
|
||||
implicitWidth: rowLayout.implicitWidth + 10 * 2
|
||||
implicitHeight: Appearance.sizes.barHeight
|
||||
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
|
||||
onPressed: {
|
||||
Weather.getData();
|
||||
Quickshell.execDetached(["notify-send",
|
||||
Translation.tr("Weather"),
|
||||
Translation.tr("Refreshing (manually triggered)")
|
||||
, "-a", "Shell"
|
||||
])
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
Weather.getData();
|
||||
Quickshell.execDetached(["notify-send",
|
||||
Translation.tr("Weather"),
|
||||
Translation.tr("Refreshing (manually triggered)")
|
||||
, "-a", "Shell"
|
||||
])
|
||||
mouse.accepted = false
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
||||
@@ -5,7 +5,6 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Qt.labs.synchronizer
|
||||
import Quickshell.Io
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
|
||||
@@ -67,11 +67,7 @@ DockButton {
|
||||
}
|
||||
|
||||
altAction: () => {
|
||||
if (Config.options.dock.pinnedApps.indexOf(appToplevel.appId) !== -1) {
|
||||
Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.filter(id => id !== appToplevel.appId)
|
||||
} else {
|
||||
Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.concat([appToplevel.appId])
|
||||
}
|
||||
TaskbarApps.togglePin(appToplevel.appId);
|
||||
}
|
||||
|
||||
contentItem: Loader {
|
||||
|
||||
@@ -25,7 +25,8 @@ Scope {
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.namespace: "quickshell:overlay"
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
// Use OnDemand for pinned widgets to allow focus switching with mouse clicks
|
||||
WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : (OverlayContext.clickableWidgets.length > 0 ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None)
|
||||
visible: true
|
||||
color: "transparent"
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ Singleton {
|
||||
{ identifier: "floatingImage", materialSymbol: "imagesmode" },
|
||||
{ identifier: "recorder", materialSymbol: "screen_record" },
|
||||
{ identifier: "resources", materialSymbol: "browse_activity" },
|
||||
{ identifier: "notes", materialSymbol: "note_stack" },
|
||||
{ identifier: "volumeMixer", materialSymbol: "volume_up" },
|
||||
]
|
||||
|
||||
|
||||
@@ -8,10 +8,11 @@ import Quickshell
|
||||
import Quickshell.Bluetooth
|
||||
import qs.modules.ii.overlay.crosshair
|
||||
import qs.modules.ii.overlay.volumeMixer
|
||||
import qs.modules.ii.overlay.floatingImage
|
||||
import qs.modules.ii.overlay.fpsLimiter
|
||||
import qs.modules.ii.overlay.recorder
|
||||
import qs.modules.ii.overlay.resources
|
||||
import qs.modules.ii.overlay.floatingImage
|
||||
import qs.modules.ii.overlay.notes
|
||||
|
||||
DelegateChooser {
|
||||
id: root
|
||||
@@ -22,5 +23,6 @@ DelegateChooser {
|
||||
DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} }
|
||||
DelegateChoice { roleValue: "recorder"; Recorder {} }
|
||||
DelegateChoice { roleValue: "resources"; Resources {} }
|
||||
DelegateChoice { roleValue: "notes"; Notes {} }
|
||||
DelegateChoice { roleValue: "volumeMixer"; VolumeMixer {} }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.ii.overlay
|
||||
|
||||
StyledOverlayWidget {
|
||||
id: root
|
||||
title: Translation.tr("Notes")
|
||||
showCenterButton: true
|
||||
|
||||
contentItem: NotesContent {
|
||||
radius: root.contentRadius
|
||||
isClickthrough: root.clickthrough
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.ii.overlay
|
||||
|
||||
OverlayBackground {
|
||||
id: root
|
||||
|
||||
property alias content: textInput.text
|
||||
property bool pendingReload: false
|
||||
property var copyListEntries: []
|
||||
property string lastParsedCopylistText: ""
|
||||
property var parsedCopylistLines: []
|
||||
property bool isClickthrough: false
|
||||
property real maxCopyButtonSize: 20
|
||||
|
||||
Component.onCompleted: {
|
||||
noteFile.reload();
|
||||
updateCopyListEntries();
|
||||
}
|
||||
|
||||
function saveContent() {
|
||||
if (!textInput)
|
||||
return;
|
||||
noteFile.setText(root.content);
|
||||
}
|
||||
|
||||
function focusAtEnd() {
|
||||
if (!textInput)
|
||||
return;
|
||||
textInput.forceActiveFocus();
|
||||
const endPos = root.content.length;
|
||||
applySelection(endPos, endPos);
|
||||
}
|
||||
|
||||
function applySelection(cursorPos, anchorPos) {
|
||||
if (!textInput)
|
||||
return;
|
||||
const textLength = root.content.length;
|
||||
const cursor = Math.max(0, Math.min(cursorPos, textLength));
|
||||
const anchor = Math.max(0, Math.min(anchorPos, textLength));
|
||||
textInput.select(anchor, cursor);
|
||||
if (cursor === anchor)
|
||||
textInput.deselect();
|
||||
}
|
||||
|
||||
function scheduleCopylistUpdate(immediate = false) {
|
||||
if (!textInput)
|
||||
return;
|
||||
if (immediate) {
|
||||
copyListDebounce?.stop();
|
||||
updateCopyListEntries();
|
||||
} else {
|
||||
copyListDebounce.restart();
|
||||
}
|
||||
}
|
||||
|
||||
function updateCopyListEntries() {
|
||||
if (!textInput)
|
||||
return;
|
||||
const textValue = root.content;
|
||||
if (!textValue || textValue.length === 0) {
|
||||
lastParsedCopylistText = "";
|
||||
parsedCopylistLines = [];
|
||||
root.copyListEntries = [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (textValue !== lastParsedCopylistText) {
|
||||
const lineRegex = /(.*?)(\r?\n|$)/g;
|
||||
let match = null;
|
||||
const parsed = [];
|
||||
while ((match = lineRegex.exec(textValue)) !== null) {
|
||||
const lineText = match[1];
|
||||
const newlineText = match[2];
|
||||
const lineStart = match.index;
|
||||
const lineEnd = lineStart + lineText.length;
|
||||
const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/);
|
||||
if (bulletMatch) {
|
||||
parsed.push({
|
||||
content: bulletMatch[1].trim(),
|
||||
start: lineStart,
|
||||
end: lineEnd
|
||||
});
|
||||
}
|
||||
if (newlineText === "")
|
||||
break;
|
||||
}
|
||||
lastParsedCopylistText = textValue;
|
||||
parsedCopylistLines = parsed;
|
||||
if (parsed.length === 0) {
|
||||
root.copyListEntries = [];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateCopylistPositions();
|
||||
}
|
||||
|
||||
function updateCopylistPositions() {
|
||||
if (!textInput || parsedCopylistLines.length === 0)
|
||||
return;
|
||||
const rawSelectionStart = textInput.selectionStart;
|
||||
const rawSelectionEnd = textInput.selectionEnd;
|
||||
const selectionStart = rawSelectionStart === -1 ? textInput.cursorPosition : rawSelectionStart;
|
||||
const selectionEnd = rawSelectionEnd === -1 ? textInput.cursorPosition : rawSelectionEnd;
|
||||
const rangeStart = Math.min(selectionStart, selectionEnd);
|
||||
const rangeEnd = Math.max(selectionStart, selectionEnd);
|
||||
|
||||
const entries = parsedCopylistLines.map(line => {
|
||||
// Don't show copy button if line is (partially) selected
|
||||
const caretIntersects = rangeEnd > line.start && rangeStart <= line.end;
|
||||
if (caretIntersects)
|
||||
return null;
|
||||
const startRect = textInput.positionToRectangle(line.start);
|
||||
let endRect = textInput.positionToRectangle(line.end);
|
||||
if (!isFinite(startRect.y))
|
||||
return null;
|
||||
if (!isFinite(endRect.y))
|
||||
endRect = startRect;
|
||||
const lineBottom = endRect.y + endRect.height;
|
||||
const rectHeight = Math.max(lineBottom - startRect.y, textInput.font.pixelSize + 8);
|
||||
return {
|
||||
content: line.content,
|
||||
y: startRect.y,
|
||||
height: rectHeight
|
||||
};
|
||||
}).filter(entry => entry !== null);
|
||||
|
||||
root.copyListEntries = entries;
|
||||
}
|
||||
|
||||
implicitWidth: 300
|
||||
implicitHeight: 200
|
||||
|
||||
ColumnLayout {
|
||||
id: contentItem
|
||||
anchors.fill: parent
|
||||
spacing: -16
|
||||
|
||||
ScrollView {
|
||||
id: editorScrollView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
ScrollBar.vertical.policy: ScrollBar.AsNeeded
|
||||
onWidthChanged: root.scheduleCopylistUpdate(true)
|
||||
|
||||
StyledTextArea { // This has to be a direct child of ScrollView for proper scrolling
|
||||
id: textInput
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
wrapMode: TextEdit.Wrap
|
||||
placeholderText: Translation.tr("Write something here...\nUse '-' to create copyable bullet points, like this:\n\nSheep fricker\n- 4x Slab\n- 1x Boat\n- 4x Redstone Dust\n- 1x Sticky Piston\n- 1x End Rod\n- 4x Redstone Repeater\n- 1x Redstone Torch\n- 1x Sheep")
|
||||
selectByMouse: true
|
||||
persistentSelection: true
|
||||
textFormat: TextEdit.PlainText
|
||||
background: null
|
||||
padding: 24
|
||||
|
||||
onTextChanged: {
|
||||
if (textInput.activeFocus) {
|
||||
saveDebounce.restart();
|
||||
}
|
||||
root.scheduleCopylistUpdate(true);
|
||||
}
|
||||
|
||||
onHeightChanged: root.scheduleCopylistUpdate(true)
|
||||
onContentHeightChanged: root.scheduleCopylistUpdate(true)
|
||||
onCursorPositionChanged: root.scheduleCopylistUpdate()
|
||||
onSelectionStartChanged: root.scheduleCopylistUpdate()
|
||||
onSelectionEndChanged: root.scheduleCopylistUpdate()
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
visible: root.copyListEntries.length > 0
|
||||
clip: true
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: root.copyListEntries
|
||||
}
|
||||
delegate: RippleButton {
|
||||
id: copyButton
|
||||
required property var modelData
|
||||
readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), root.maxCopyButtonSize)
|
||||
readonly property real iconSizeLocal: Appearance.font.pixelSize.normal
|
||||
readonly property real hitPadding: 6
|
||||
property bool justCopied: false
|
||||
|
||||
implicitHeight: lineHeight
|
||||
implicitWidth: lineHeight
|
||||
buttonRadius: height / 2
|
||||
y: modelData.y
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 10
|
||||
z: 5
|
||||
|
||||
Timer {
|
||||
id: resetState
|
||||
interval: 700
|
||||
onTriggered: {
|
||||
copyButton.justCopied = false;
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
Quickshell.clipboardText = copyButton.modelData.content;
|
||||
justCopied = true;
|
||||
resetState.start();
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors.centerIn: parent
|
||||
MaterialSymbol {
|
||||
id: iconItem
|
||||
anchors.centerIn: parent
|
||||
text: copyButton.justCopied ? "check" : "content_copy"
|
||||
iconSize: copyButton.iconSizeLocal
|
||||
color: Appearance.colors.colOnLayer1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: statusLabel
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: 16
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved ")
|
||||
color: Appearance.colors.colSubtext
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: saveDebounce
|
||||
interval: 500
|
||||
repeat: false
|
||||
onTriggered: saveContent()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: copyListDebounce
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: updateCopylistPositions()
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: noteFile
|
||||
path: Qt.resolvedUrl(Directories.notesPath)
|
||||
onLoaded: {
|
||||
root.content = noteFile.text();
|
||||
if (root.content !== root.content) {
|
||||
const previousCursor = textInput.cursorPosition;
|
||||
const previousAnchor = textInput.selectionStart;
|
||||
root.content = root.content;
|
||||
applySelection(previousCursor, previousAnchor);
|
||||
}
|
||||
if (pendingReload) {
|
||||
pendingReload = false;
|
||||
Qt.callLater(root.focusAtEnd);
|
||||
}
|
||||
Qt.callLater(root.updateCopyListEntries);
|
||||
}
|
||||
onLoadFailed: error => {
|
||||
if (error === FileViewError.FileNotFound) {
|
||||
root.content = "";
|
||||
noteFile.setText(root.content);
|
||||
if (pendingReload) {
|
||||
pendingReload = false;
|
||||
Qt.callLater(root.focusAtEnd);
|
||||
}
|
||||
Qt.callLater(root.updateCopyListEntries);
|
||||
} else {
|
||||
console.log("[Overlay Notes] Error loading file: " + error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Qt.labs.synchronizer
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
|
||||
@@ -167,6 +167,9 @@ Scope {
|
||||
function toggle() {
|
||||
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
|
||||
}
|
||||
function workspacesToggle() {
|
||||
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
|
||||
}
|
||||
function close() {
|
||||
GlobalStates.overviewOpen = false;
|
||||
}
|
||||
@@ -189,6 +192,14 @@ Scope {
|
||||
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
|
||||
}
|
||||
}
|
||||
GlobalShortcut {
|
||||
name: "overviewWorkspacesToggle"
|
||||
description: "Toggles overview on press"
|
||||
|
||||
onPressed: {
|
||||
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
|
||||
}
|
||||
}
|
||||
GlobalShortcut {
|
||||
name: "overviewClose"
|
||||
description: "Closes overview"
|
||||
|
||||
@@ -285,48 +285,36 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: Array.from({ length: root.messageBlocks.length }, (msg, i) => {
|
||||
return ({
|
||||
type: root.messageBlocks[i].type
|
||||
})
|
||||
});
|
||||
values: root.messageBlocks
|
||||
}
|
||||
|
||||
delegate: DelegateChooser {
|
||||
id: messageDelegate
|
||||
role: "type"
|
||||
|
||||
DelegateChoice { roleValue: "code"; MessageCodeBlock {
|
||||
required property int index
|
||||
property var thisBlock: root.messageBlocks[index]
|
||||
editing: root.editing
|
||||
renderMarkdown: root.renderMarkdown
|
||||
enableMouseSelection: root.enableMouseSelection
|
||||
segmentContent: thisBlock.content
|
||||
segmentLang: thisBlock.lang
|
||||
segmentContent: modelData.content
|
||||
segmentLang: modelData.lang
|
||||
messageData: root.messageData
|
||||
} }
|
||||
DelegateChoice { roleValue: "think"; MessageThinkBlock {
|
||||
required property int index
|
||||
property var thisBlock: root.messageBlocks[index]
|
||||
editing: root.editing
|
||||
renderMarkdown: root.renderMarkdown
|
||||
enableMouseSelection: root.enableMouseSelection
|
||||
segmentContent: thisBlock.content
|
||||
segmentContent: modelData.content
|
||||
messageData: root.messageData
|
||||
done: root.messageData?.done ?? false
|
||||
completed: thisBlock.completed ?? false
|
||||
completed: modelData.completed ?? false
|
||||
} }
|
||||
DelegateChoice { roleValue: "text"; MessageTextBlock {
|
||||
required property int index
|
||||
property var thisBlock: root.messageBlocks[index]
|
||||
editing: root.editing
|
||||
renderMarkdown: root.renderMarkdown
|
||||
enableMouseSelection: root.enableMouseSelection
|
||||
segmentContent: thisBlock.content
|
||||
segmentContent: modelData.content
|
||||
messageData: root.messageData
|
||||
done: root.messageData?.done ?? false
|
||||
forceDisableChunkSplitting: root.messageData?.content.includes("```") ?? true
|
||||
|
||||
@@ -156,7 +156,6 @@ Item {
|
||||
property bool editing: root.editing
|
||||
property bool renderMarkdown: root.renderMarkdown
|
||||
property bool enableMouseSelection: root.enableMouseSelection
|
||||
property string segmentContent: root.segmentContent
|
||||
property var messageData: root.messageData
|
||||
property bool done: root.done
|
||||
|
||||
@@ -165,6 +164,7 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
segmentContent: root.segmentContent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ AndroidQuickToggleButton {
|
||||
name: Translation.tr("Bluetooth")
|
||||
statusText: BluetoothStatus.firstActiveDevice?.name ?? Translation.tr("No device")
|
||||
|
||||
available: BluetoothStatus.available
|
||||
toggled: BluetoothStatus.enabled
|
||||
buttonIcon: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled"
|
||||
mainAction: () => {
|
||||
@@ -27,4 +28,3 @@ AndroidQuickToggleButton {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ AndroidQuickToggleButton {
|
||||
|
||||
name: Translation.tr("EasyEffects")
|
||||
|
||||
available: EasyEffects.available
|
||||
toggled: EasyEffects.active
|
||||
buttonIcon: "graphic_eq"
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ GroupButton {
|
||||
required property string name
|
||||
required property var mainAction
|
||||
property string statusText: toggled ? Translation.tr("Active") : Translation.tr("Inactive")
|
||||
property bool available: true
|
||||
|
||||
required property real baseCellWidth
|
||||
required property real baseCellHeight
|
||||
@@ -42,6 +43,7 @@ GroupButton {
|
||||
|
||||
signal openMenu()
|
||||
|
||||
enabled: available || editMode
|
||||
padding: 6
|
||||
horizontalPadding: padding
|
||||
verticalPadding: padding
|
||||
@@ -52,8 +54,8 @@ GroupButton {
|
||||
colBackgroundToggledActive: (altAction && expandedSize) ? Appearance.colors.colLayer2Active : Appearance.colors.colPrimaryActive
|
||||
buttonRadius: toggled ? Appearance.rounding.large : height / 2
|
||||
buttonRadiusPressed: Appearance.rounding.normal
|
||||
property color colText: (toggled && !(altAction && expandedSize)) ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer2
|
||||
property color colIcon: expandedSize ? (root.toggled ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer3) : colText
|
||||
property color colText: (toggled && !(altAction && expandedSize) && enabled) ? Appearance.colors.colOnPrimary : ColorUtils.transparentize(Appearance.colors.colOnLayer2, enabled ? 0 : 0.7)
|
||||
property color colIcon: expandedSize ? ((root.toggled) ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer3) : colText
|
||||
|
||||
onClicked: {
|
||||
if (root.expandedSize && root.altAction) root.altAction();
|
||||
|
||||
@@ -15,7 +15,7 @@ MouseArea {
|
||||
readonly property bool isLow: percentage <= Config.options.battery.low / 100
|
||||
|
||||
implicitHeight: batteryProgress.implicitHeight
|
||||
hoverEnabled: true
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
|
||||
ClippedProgressBar {
|
||||
id: batteryProgress
|
||||
|
||||
@@ -9,7 +9,7 @@ MouseArea {
|
||||
property bool alwaysShowAllResources: false
|
||||
implicitHeight: columnLayout.implicitHeight
|
||||
implicitWidth: columnLayout.implicitWidth
|
||||
hoverEnabled: true
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
|
||||
ColumnLayout {
|
||||
id: columnLayout
|
||||
|
||||
@@ -33,8 +33,7 @@ Item {
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
|
||||
Bar.ClockWidgetPopup {
|
||||
hoverTarget: mouseArea
|
||||
|
||||
@@ -28,7 +28,7 @@ MouseArea {
|
||||
}
|
||||
|
||||
acceptedButtons: Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton | Qt.RightButton | Qt.LeftButton
|
||||
hoverEnabled: true
|
||||
hoverEnabled: !Config.options.bar.tooltips.clickToShow
|
||||
onPressed: (event) => {
|
||||
if (event.button === Qt.MiddleButton) {
|
||||
activePlayer.togglePlaying();
|
||||
|
||||
@@ -55,6 +55,20 @@ ContentPage {
|
||||
ContentSection {
|
||||
icon: "clock_loader_40"
|
||||
title: Translation.tr("Widget: Clock")
|
||||
id: settingsClock
|
||||
|
||||
function stylePresent(styleName) {
|
||||
if (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === styleName) {
|
||||
return true;
|
||||
}
|
||||
if (Config.options.background.widgets.clock.styleLocked === styleName) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
readonly property bool digitalPresent: stylePresent("digital")
|
||||
readonly property bool cookiePresent: stylePresent("cookie")
|
||||
|
||||
ConfigRow {
|
||||
Layout.fillWidth: true
|
||||
@@ -107,6 +121,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: !Config.options.background.widgets.clock.showOnlyWhenLocked
|
||||
title: Translation.tr("Clock style")
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.background.widgets.clock.style
|
||||
@@ -129,7 +144,29 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.widgets.clock.style === "digital"
|
||||
title: Translation.tr("Clock style (locked)")
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.background.widgets.clock.styleLocked
|
||||
onSelected: newValue => {
|
||||
Config.options.background.widgets.clock.styleLocked = newValue;
|
||||
}
|
||||
options: [
|
||||
{
|
||||
displayName: Translation.tr("Digital"),
|
||||
icon: "timer_10",
|
||||
value: "digital"
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("Cookie"),
|
||||
icon: "cookie",
|
||||
value: "cookie"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: settingsClock.digitalPresent
|
||||
title: Translation.tr("Digital clock settings")
|
||||
|
||||
ConfigSwitch {
|
||||
@@ -143,7 +180,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.widgets.clock.style === "cookie"
|
||||
visible: settingsClock.cookiePresent
|
||||
title: Translation.tr("Cookie clock settings")
|
||||
|
||||
ConfigSwitch {
|
||||
@@ -197,7 +234,7 @@ ContentPage {
|
||||
ConfigRow {
|
||||
|
||||
ConfigSwitch {
|
||||
enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle === "dots" || Config.options.background.widgets.clock.cookie.dialNumberStyle === "full"
|
||||
enabled: Config.options.background.widgets.clock.cookie.dialNumberStyle === "dots" || Config.options.background.widgets.clock.cookie.dialNumberStyle === "full"
|
||||
buttonIcon: "brightness_7"
|
||||
text: Translation.tr("Hour marks")
|
||||
checked: Config.options.background.widgets.clock.cookie.hourMarks
|
||||
@@ -213,7 +250,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle !== "numbers"
|
||||
enabled: Config.options.background.widgets.clock.cookie.dialNumberStyle !== "numbers"
|
||||
buttonIcon: "timer_10"
|
||||
text: Translation.tr("Digits in the middle")
|
||||
checked: Config.options.background.widgets.clock.cookie.timeIndicators
|
||||
@@ -231,7 +268,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.widgets.clock.style === "cookie"
|
||||
visible: settingsClock.cookiePresent
|
||||
title: Translation.tr("Dial style")
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.background.widgets.clock.cookie.dialNumberStyle
|
||||
@@ -270,7 +307,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.widgets.clock.style === "cookie"
|
||||
visible: settingsClock.cookiePresent
|
||||
title: Translation.tr("Hour hand")
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.background.widgets.clock.cookie.hourHandStyle
|
||||
@@ -303,7 +340,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.widgets.clock.style === "cookie"
|
||||
visible: settingsClock.cookiePresent
|
||||
title: Translation.tr("Minute hand")
|
||||
|
||||
ConfigSelectionArray {
|
||||
@@ -342,7 +379,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.widgets.clock.style === "cookie"
|
||||
visible: settingsClock.cookiePresent
|
||||
title: Translation.tr("Second hand")
|
||||
|
||||
ConfigSelectionArray {
|
||||
@@ -376,7 +413,7 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.widgets.clock.style === "cookie"
|
||||
visible: settingsClock.cookiePresent
|
||||
title: Translation.tr("Date style")
|
||||
|
||||
ConfigSelectionArray {
|
||||
|
||||
@@ -148,18 +148,18 @@ ContentPage {
|
||||
ConfigSwitch {
|
||||
buttonIcon: "keep"
|
||||
text: Translation.tr('Make icons pinned by default')
|
||||
checked: Config.options.bar.tray.invertPinnedItems
|
||||
checked: Config.options.tray.invertPinnedItems
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.tray.invertPinnedItems = checked;
|
||||
Config.options.tray.invertPinnedItems = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "colors"
|
||||
text: Translation.tr('Tint icons')
|
||||
checked: Config.options.bar.tray.monochromeIcons
|
||||
checked: Config.options.tray.monochromeIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.tray.monochromeIcons = checked;
|
||||
Config.options.tray.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,4 +334,17 @@ ContentPage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
icon: "tooltip"
|
||||
title: Translation.tr("Tooltips")
|
||||
ConfigSwitch {
|
||||
buttonIcon: "ads_click"
|
||||
text: Translation.tr("Click to show")
|
||||
checked: Config.options.bar.tooltips.clickToShow
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.tooltips.clickToShow = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ ContentPage {
|
||||
// Use a nerdfont to see the icons
|
||||
options: ([
|
||||
"", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "⌘", "", "", ""
|
||||
"", "", "", "", "", "", "⌘", "", "", ""
|
||||
]).map(icon => { return {
|
||||
displayName: icon,
|
||||
value: icon
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
## Waffle
|
||||
|
||||
A recreation of Windoes. It's WIP!
|
||||
|
||||
- If you install illogical-impulse fully, you can press Super+Alt+W to switch to this style.
|
||||
- If you're just copying the Quickshell config, run the config as usual (`qs -c ii`) then run `qs -c ii ipc call panelFamily cycle`
|
||||
|
||||
## From EWW version to Quickshell
|
||||
|
||||
Just a reflection, in case anyone's interested. My blog is probably a better place for this, but it does not exist. Besides, this is going to change as I do more stuff. Currently there's just the bar.
|
||||
|
||||
### Improvements
|
||||
|
||||
- QtQuick's `Button` has the `{top/bottom/left/right}Inset` properties, so we can have clickable regions expanding beyond the button background for free. With EWW it was annoying to wrap the button content with an `eventbox` that has some padding, then somehow use CSS selectors to make sure hovering effects work. I have to admit, (a large) part of that annoyance was with how bad my copy-pasting coding practice was at the time, but still...
|
||||
|
||||
- Fancy effects: Gtk3 CSS does not support transformations. In QtQuick we can smack `rotation` and `scale` almost everywhere, so it's simple to make bouncy icons and rotating chevrons
|
||||
|
||||
- Quickshell provides a system tray service (EWW does now but didn't at the time I created the EWW Windoes version), so now there's no Waybar needed for the tray.
|
||||
|
||||
- QtQuick has `Loader`s, so we can have this live-switchable from the main style without killing the widget system, moving styles to the correct folder, and relaunching.
|
||||
|
||||
- This time my computer is powerful enough to run a VM, so I don't have to occasionally reboot to take quick screenshots for reference. I try to make everything pixel-perfect so this is necessary. Speaking about pixel-perfectness, in the EWW version I hardcoded sizes, but this time I'm still doing that (lol), BUT that's normal and not a problem because Qt has the `QT_SCALE_FACTOR` env var for scaling. (Please feel free to prove me wrong in saying Gtk3 doesn't have that magic)
|
||||
|
||||
### Challenges
|
||||
|
||||
- Qt is not Gtk and definitely not React
|
||||
- We don't get directional border on QtQuick `Rectangle`s like in CSS. I was able to get around this with manual drawing, but it was a bit more work
|
||||
|
||||
- Fluent Icons is difficult to use, compared to Material Symbols
|
||||
- No React, so no clean use via a library.
|
||||
- If we use the font, there's no proper, searchable **codepoint** cheatsheet like Nerd Fonts, and there's no ligatures
|
||||
- I resorted to downloading individual SVGs. Not that nice, but it's better than scanning the whole table of icons every time I want one. For this we have fluenticon.com and fluenticons.co, but icons are awkwardly named and there's no alias. Why is the reload/refresh icon called "arrow-sync"? Well, the name is not misleading, but arguably reload/refresh are more common actions. From Fluent Design's [page on Iconography](https://fluent2.microsoft.design/iconography):
|
||||
|
||||
> Fluent system icons are literal metaphors and are named for the shape or object they represent, not the functionality they provide
|
||||
|
||||
"sync" is functionality.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
WBarAttachedPanelContent {
|
||||
id: root
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
topLeftRadius: root.border.radius - root.border.border.width
|
||||
topRightRadius: topLeftRadius
|
||||
color: Looks.colors.bgPanelBody
|
||||
|
||||
implicitWidth: 360
|
||||
implicitHeight: 380
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: false
|
||||
Layout.fillWidth: true
|
||||
color: Looks.colors.bgPanelSeparator
|
||||
implicitHeight: 1
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: false
|
||||
Layout.fillWidth: true
|
||||
bottomLeftRadius: root.border.radius - root.border.border.width
|
||||
bottomRightRadius: bottomLeftRadius
|
||||
color: Looks.colors.bgPanelFooter
|
||||
|
||||
implicitWidth: 360
|
||||
implicitHeight: 47
|
||||
|
||||
// Battery button
|
||||
WPanelFooterButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
|
||||
contentItem: Row {
|
||||
spacing: 4
|
||||
|
||||
FluentIcon {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon: WIcons.batteryIcon
|
||||
}
|
||||
WText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: `${Math.round(Battery.percentage * 100) || 0}%`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Settings button
|
||||
WPanelFooterButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
|
||||
contentItem: FluentIcon {
|
||||
icon: "settings"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Hyprland
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
Scope {
|
||||
id: root
|
||||
|
||||
Connections {
|
||||
target: GlobalStates
|
||||
|
||||
function onSidebarLeftOpenChanged() {
|
||||
if (GlobalStates.sidebarLeftOpen) barLoader.active = true;
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: barLoader
|
||||
active: GlobalStates.sidebarLeftOpen
|
||||
sourceComponent: PanelWindow {
|
||||
id: panelWindow
|
||||
exclusiveZone: 0
|
||||
WlrLayershell.namespace: "quickshell:actionCenter"
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
||||
color: "transparent"
|
||||
|
||||
anchors {
|
||||
bottom: Config.options.waffles.bar.bottom
|
||||
top: !Config.options.waffles.bar.bottom
|
||||
right: true
|
||||
}
|
||||
|
||||
implicitWidth: content.implicitWidth + content.visualMargin * 2
|
||||
implicitHeight: content.implicitHeight + content.visualMargin * 2
|
||||
|
||||
HyprlandFocusGrab {
|
||||
id: focusGrab
|
||||
active: true
|
||||
windows: [panelWindow]
|
||||
onCleared: content.close();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: GlobalStates
|
||||
function onSidebarLeftOpenChanged() {
|
||||
if (!GlobalStates.sidebarLeftOpen) content.close();
|
||||
}
|
||||
}
|
||||
|
||||
ActionCenterContent {
|
||||
id: content
|
||||
anchors.centerIn: parent
|
||||
|
||||
onClosed: {
|
||||
barLoader.active = false;
|
||||
GlobalStates.sidebarLeftOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleOpen() {
|
||||
GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen;
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
target: "sidebarLeft"
|
||||
|
||||
function toggle() {
|
||||
root.toggleOpen();
|
||||
}
|
||||
}
|
||||
|
||||
GlobalShortcut {
|
||||
name: "sidebarLeftToggle"
|
||||
description: "Toggles left sidebar on press"
|
||||
|
||||
onPressed: root.toggleOpen();
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,12 @@ BarButton {
|
||||
rightInset: 2
|
||||
implicitWidth: height - topInset - bottomInset + leftInset + rightInset
|
||||
|
||||
property real pressedScale: 5/6
|
||||
|
||||
onDownChanged: {
|
||||
scaleAnim.duration = root.down ? 150 : 200
|
||||
scaleAnim.easing.bezierCurve = root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
|
||||
contentItem.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
|
||||
contentItem.scale = root.down ? root.pressedScale : 1 // If/When we do dragging, the scale is 1.25
|
||||
}
|
||||
|
||||
background: Item {
|
||||
@@ -45,9 +47,7 @@ BarButton {
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 5
|
||||
active: root.multiple
|
||||
sourceComponent: BackgroundAcrylicRectangle {
|
||||
|
||||
}
|
||||
sourceComponent: BackgroundAcrylicRectangle {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ BarButton {
|
||||
|
||||
component BackgroundAcrylicRectangle: AcrylicRectangle {
|
||||
shiny: ((root.hovered && !root.down) || root.checked)
|
||||
color: root.colBackground
|
||||
color: root.color
|
||||
border.width: 1
|
||||
border.color: root.colBackgroundBorder
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ Kirigami.Icon {
|
||||
property real implicitSize: 26
|
||||
implicitWidth: implicitSize
|
||||
implicitHeight: implicitSize
|
||||
|
||||
animated: true
|
||||
roundToIconSize: false
|
||||
fallback: root.iconName
|
||||
source: tryCustomIcon ? `${Looks.iconsPath}/${root.iconName}${!root.separateLightDark ? "" : Looks.dark ? "-dark" : "-light"}.svg` : fallback
|
||||
|
||||
@@ -8,11 +8,14 @@ import qs.modules.waffle.looks
|
||||
Button {
|
||||
id: root
|
||||
|
||||
signal altAction()
|
||||
signal middleClickAction()
|
||||
property var altAction: () => {}
|
||||
property var middleClickAction: () => {}
|
||||
|
||||
property color colBackground
|
||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
||||
property color colBackgroundHover: Looks.colors.bg1Hover
|
||||
property color colBackgroundActive: Looks.colors.bg1Active
|
||||
property color colBackgroundBorder
|
||||
property color color
|
||||
Layout.fillHeight: true
|
||||
topInset: 4
|
||||
bottomInset: 4
|
||||
@@ -37,16 +40,16 @@ Button {
|
||||
}
|
||||
}
|
||||
|
||||
colBackground: {
|
||||
colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, (root.checked || root.hovered) ? Looks.contentTransparency : 1)
|
||||
color: {
|
||||
if (root.down) {
|
||||
return Looks.colors.bg1Active
|
||||
return root.colBackgroundActive
|
||||
} else if ((root.hovered && !root.down) || root.checked) {
|
||||
return Looks.colors.bg1Hover
|
||||
return root.colBackgroundHover
|
||||
} else {
|
||||
return ColorUtils.transparentize(Looks.colors.bg1)
|
||||
return root.colBackground
|
||||
}
|
||||
}
|
||||
colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, root.checked ? Looks.contentTransparency : 1)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@@ -66,7 +69,8 @@ Button {
|
||||
|
||||
background: AcrylicRectangle {
|
||||
shiny: ((root.hovered && !root.down) || root.checked)
|
||||
color: root.colBackground
|
||||
color: root.color
|
||||
radius: Looks.radius.medium
|
||||
border.width: 1
|
||||
border.color: root.colBackgroundBorder
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar
|
||||
|
||||
BarButton {
|
||||
id: root
|
||||
|
||||
property alias iconName: iconContent.icon
|
||||
property alias iconSource: iconContent.source
|
||||
property alias iconSize: iconContent.implicitSize
|
||||
property alias iconRotation: iconContent.rotation
|
||||
property alias iconMonochrome: iconContent.monochrome
|
||||
property alias iconScale: iconContent.scale
|
||||
property alias tooltipText: tooltip.text
|
||||
property alias overlayingItems: iconContent.data
|
||||
|
||||
implicitWidth: 32
|
||||
|
||||
contentItem: Item {
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: iconContent.implicitWidth
|
||||
implicitHeight: iconContent.implicitHeight
|
||||
|
||||
FluentIcon {
|
||||
id: iconContent
|
||||
anchors.centerIn: parent
|
||||
implicitSize: 16
|
||||
icon: root.iconName
|
||||
monochrome: false
|
||||
}
|
||||
}
|
||||
|
||||
BarToolTip {
|
||||
id: tooltip
|
||||
extraVisibleCondition: root.shouldShowTooltip && text !== ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
BarPopup {
|
||||
id: root
|
||||
default property var menuData
|
||||
property var model: [
|
||||
{ iconName: "start-here", text: "Start", action: () => {print("hello")} },
|
||||
{ type : "separator" },
|
||||
]
|
||||
readonly property bool hasIcons: model.some(item => item.iconName !== undefined && item.iconName !== "")
|
||||
padding: 2
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: root.model
|
||||
delegate: DelegateChooser {
|
||||
role: "type"
|
||||
DelegateChoice {
|
||||
roleValue: "separator"
|
||||
Rectangle {
|
||||
Layout.topMargin: 2
|
||||
Layout.bottomMargin: 2
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 1
|
||||
color: Looks.colors.bg0Border
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: undefined
|
||||
WButton {
|
||||
id: btn
|
||||
Layout.fillWidth: true
|
||||
|
||||
required property var modelData
|
||||
forceShowIcon: root.hasIcons
|
||||
icon.name: modelData.iconName ? modelData.iconName : ""
|
||||
monochromeIcon: modelData.monochromeIcon ?? true
|
||||
text: modelData.text ? modelData.text : ""
|
||||
|
||||
onClicked: {
|
||||
if (modelData.action) modelData.action();
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Loader {
|
||||
id: root
|
||||
|
||||
required property var contentItem
|
||||
property real padding: Looks.radius.large - Looks.radius.medium
|
||||
property bool noSmoothClosing: !Config.options.waffles.smootherAnimations
|
||||
property bool closeOnFocusLost: true
|
||||
signal focusCleared()
|
||||
|
||||
property Item anchorItem: parent
|
||||
property real visualMargin: 12
|
||||
readonly property bool barAtBottom: Config.options.waffles.bar.bottom
|
||||
property real ambientShadowWidth: 1
|
||||
|
||||
onFocusCleared: {
|
||||
if (!root.closeOnFocusLost) return;
|
||||
root.close()
|
||||
}
|
||||
|
||||
function grabFocus() { // Doesn't work
|
||||
item.grabFocus();
|
||||
}
|
||||
|
||||
function close() {
|
||||
item.close();
|
||||
}
|
||||
|
||||
function updateAnchor() {
|
||||
item?.anchor.updateAnchor();
|
||||
}
|
||||
|
||||
active: false
|
||||
visible: active
|
||||
sourceComponent: PopupWindow {
|
||||
id: popupWindow
|
||||
visible: true
|
||||
Component.onCompleted: {
|
||||
openAnim.start();
|
||||
}
|
||||
|
||||
anchor {
|
||||
adjustment: PopupAdjustment.ResizeY | PopupAdjustment.SlideX
|
||||
item: root.anchorItem
|
||||
gravity: root.barAtBottom ? Edges.Top : Edges.Bottom
|
||||
edges: root.barAtBottom ? Edges.Top : Edges.Bottom
|
||||
}
|
||||
|
||||
HyprlandFocusGrab {
|
||||
id: focusGrab
|
||||
active: true
|
||||
windows: [popupWindow]
|
||||
onCleared: root.focusCleared();
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (root.noSmoothClosing) root.active = false;
|
||||
else closeAnim.start();
|
||||
}
|
||||
|
||||
function grabFocus() {
|
||||
focusGrab.active = true; // Doesn't work
|
||||
}
|
||||
|
||||
implicitWidth: realContent.implicitWidth + (root.ambientShadowWidth * 2) + (root.visualMargin * 2)
|
||||
implicitHeight: realContent.implicitHeight + (root.ambientShadowWidth * 2) + (root.visualMargin * 2)
|
||||
|
||||
property real sourceEdgeMargin: -implicitHeight
|
||||
PropertyAnimation {
|
||||
id: openAnim
|
||||
target: popupWindow
|
||||
property: "sourceEdgeMargin"
|
||||
to: (root.ambientShadowWidth + root.visualMargin)
|
||||
duration: 200
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
SequentialAnimation {
|
||||
id: closeAnim
|
||||
PropertyAnimation {
|
||||
target: popupWindow
|
||||
property: "sourceEdgeMargin"
|
||||
to: -implicitHeight
|
||||
duration: 150
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
root.active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
color: "transparent"
|
||||
WAmbientShadow {
|
||||
target: realContent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: realContent
|
||||
z: 1
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: root.barAtBottom ? undefined : parent.top
|
||||
bottom: root.barAtBottom ? parent.bottom : undefined
|
||||
margins: root.ambientShadowWidth + root.visualMargin
|
||||
// Opening anim
|
||||
bottomMargin: root.barAtBottom ? popupWindow.sourceEdgeMargin : (root.ambientShadowWidth + root.visualMargin)
|
||||
topMargin: root.barAtBottom ? (root.ambientShadowWidth + root.visualMargin) : popupWindow.sourceEdgeMargin
|
||||
}
|
||||
color: Looks.colors.bg1
|
||||
radius: Looks.radius.large
|
||||
|
||||
// test
|
||||
implicitWidth: root.contentItem.implicitWidth + (root.padding * 2)
|
||||
implicitHeight: root.contentItem.implicitHeight + (root.padding * 2)
|
||||
|
||||
children: [root.contentItem]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,10 @@ import qs.modules.waffle.looks
|
||||
AppButton {
|
||||
id: root
|
||||
|
||||
iconName: "system-search"
|
||||
iconName: checked ? "system-search-checked" : "system-search"
|
||||
separateLightDark: true
|
||||
|
||||
checked: GlobalStates.overviewOpen
|
||||
onClicked: {
|
||||
GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now...
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import org.kde.kirigami as Kirigami
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
@@ -10,7 +11,7 @@ AppButton {
|
||||
id: root
|
||||
|
||||
leftInset: Config.options.waffles.bar.leftAlignApps ? 12 : 0
|
||||
iconName: "start-here"
|
||||
iconName: down ? "start-here-pressed" : "start-here"
|
||||
|
||||
onClicked: {
|
||||
GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now...
|
||||
@@ -21,4 +22,45 @@ AppButton {
|
||||
text: Translation.tr("Start")
|
||||
extraVisibleCondition: root.shouldShowTooltip
|
||||
}
|
||||
|
||||
altAction: () => {
|
||||
contextMenu.active = true;
|
||||
}
|
||||
|
||||
BarMenu {
|
||||
id: contextMenu
|
||||
|
||||
model: [
|
||||
{
|
||||
text: Translation.tr("Terminal"),
|
||||
action: () => {
|
||||
Quickshell.execDetached(["bash", "-c", Config.options.apps.terminal]);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: Translation.tr("Task Manager"),
|
||||
action: () => {
|
||||
Quickshell.execDetached(["bash", "-c", Config.options.apps.taskManager]);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: Translation.tr("Settings"),
|
||||
action: () => {
|
||||
Quickshell.execDetached(["qs", "-p", Quickshell.shellPath("settings.qml")]);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: Translation.tr("File Explorer"),
|
||||
action: () => {
|
||||
Qt.openUrlExternally(Directories.home);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: Translation.tr("Search"),
|
||||
action: () => {
|
||||
Quickshell.execDetached(["qs", "-p", Quickshell.shellPath(""), "ipc", "call", "overview", "toggle"]);
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import qs.modules.waffle.looks
|
||||
BarButton {
|
||||
id: root
|
||||
|
||||
checked: GlobalStates.sidebarRightOpen
|
||||
checked: GlobalStates.sidebarLeftOpen
|
||||
onClicked: {
|
||||
GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; // For now...
|
||||
GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen;
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
@@ -85,11 +85,13 @@ BarButton {
|
||||
BarToolTip {
|
||||
extraVisibleCondition: root.shouldShowTooltip && volumeHoverArea.containsMouse
|
||||
text: Translation.tr("Speakers (%1): %2") //
|
||||
.arg(Audio.sink?.nickname || Audio.sink?.description || Translation.tr("Unknown")) //
|
||||
.arg(`${Math.round(Audio.sink?.audio.volume * 100) || 0}%`) //
|
||||
.arg(Audio.sink?.nickname || Audio.sink?.description || Translation.tr("Unknown")) //
|
||||
.arg(Audio.sink?.audio.muted ? Translation.tr("Muted") : `${Math.round(Audio.sink?.audio.volume * 100) || 0}%`) //
|
||||
}
|
||||
BarToolTip {
|
||||
extraVisibleCondition: root.shouldShowTooltip && batteryHoverArea.containsMouse
|
||||
text: Translation.tr("Battery: %1").arg(`${Math.round(Battery.percentage * 100) || 0}%`)
|
||||
text: Translation.tr("Battery: %1%2") //
|
||||
.arg(`${Math.round(Battery.percentage * 100) || 0}%`) //
|
||||
.arg(Battery.isPluggedIn ? (" " + Translation.tr("(Plugged in)")) : "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import qs.modules.waffle.looks
|
||||
AppButton {
|
||||
id: root
|
||||
|
||||
iconName: "task-view"
|
||||
iconName: (down && !checked) ? "task-view-pressed" : "task-view"
|
||||
pressedScale: checked ? 5/6 : 1
|
||||
separateLightDark: true
|
||||
|
||||
checked: GlobalStates.overviewOpen
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar.tray
|
||||
|
||||
BarIconButton {
|
||||
id: root
|
||||
|
||||
visible: Updates.updateAdvised || Updates.updateStronglyAdvised
|
||||
padding: 4
|
||||
iconName: "arrow-sync"
|
||||
iconSize: 20 // Needed because the icon appears to have some padding
|
||||
tooltipText: Translation.tr("Get the latest features and security improvements with\nthe newest feature update.\n\n%1 packages").arg(Updates.count)
|
||||
|
||||
onClicked: {
|
||||
Quickshell.execDetached(["bash", "-c", Config.options.apps.update]);
|
||||
}
|
||||
|
||||
overlayingItems: Rectangle {
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: 1
|
||||
}
|
||||
implicitWidth: 8
|
||||
implicitHeight: implicitWidth
|
||||
radius: height / 2
|
||||
color: Updates.updateStronglyAdvised ? Looks.colors.warning : Looks.colors.accent
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,7 @@ import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
Scope {
|
||||
id: bar
|
||||
property bool showBarBackground: Config.options.bar.showBackground
|
||||
id: root
|
||||
|
||||
LazyLoader {
|
||||
id: barLoader
|
||||
|
||||
@@ -4,6 +4,7 @@ import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar.tasks
|
||||
import qs.modules.waffle.bar.tray
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
@@ -68,6 +69,8 @@ Rectangle {
|
||||
shown: Config.options.waffles.bar.leftAlignApps
|
||||
sourceComponent: WidgetsButton {}
|
||||
}
|
||||
Tray {}
|
||||
UpdatesButton {}
|
||||
SystemButton {}
|
||||
TimeButton {}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ AppButton {
|
||||
onClicked: {
|
||||
GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen
|
||||
}
|
||||
onDownChanged: {
|
||||
scaleAnim.duration = root.down ? 150 : 200
|
||||
scaleAnim.easing.bezierCurve = root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
|
||||
iconWidget.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors {
|
||||
@@ -41,6 +46,13 @@ AppButton {
|
||||
id: iconWidget
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconName: root.iconName
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
id: scaleAnim
|
||||
easing.type: Easing.BezierSpline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar
|
||||
import Quickshell
|
||||
@@ -16,6 +17,7 @@ AppButton {
|
||||
property bool hasWindows: appEntry.toplevels.length > 0
|
||||
|
||||
signal hoverPreviewRequested()
|
||||
signal hoverPreviewDismissed()
|
||||
|
||||
multiple: appEntry.toplevels.length > 1
|
||||
checked: active
|
||||
@@ -37,12 +39,18 @@ AppButton {
|
||||
}
|
||||
}
|
||||
|
||||
onMiddleClickAction: {
|
||||
middleClickAction: () => {
|
||||
if (root.desktopEntry) {
|
||||
desktopEntry.execute()
|
||||
}
|
||||
}
|
||||
|
||||
altAction: () => {
|
||||
root.hoverPreviewDismissed()
|
||||
root.hoverTimer.stop()
|
||||
contextMenu.active = true;
|
||||
}
|
||||
|
||||
// Active indicator
|
||||
Rectangle {
|
||||
id: activeIndicator
|
||||
@@ -74,4 +82,44 @@ AppButton {
|
||||
extraVisibleCondition: root.shouldShowTooltip && !root.hasWindows
|
||||
text: desktopEntry ? desktopEntry.name : appEntry.appId
|
||||
}
|
||||
|
||||
BarMenu {
|
||||
id: contextMenu
|
||||
|
||||
model: [
|
||||
...((root.desktopEntry?.actions.length > 0) ? root.desktopEntry.actions.map(action =>({
|
||||
iconName: action.icon,
|
||||
text: action.name,
|
||||
action: () => {
|
||||
action.execute()
|
||||
}
|
||||
})).concat({ type: "separator" }) : []),
|
||||
{
|
||||
iconName: root.iconName,
|
||||
text: root.desktopEntry ? root.desktopEntry.name : StringUtils.toTitleCase(appEntry.appId),
|
||||
monochromeIcon: false,
|
||||
action: () => {
|
||||
if (root.desktopEntry) {
|
||||
root.desktopEntry.execute()
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
iconName: root.appEntry.pinned ? "pin-off" : "pin",
|
||||
text: root.appEntry.pinned ? qsTr("Unpin from taskbar") : qsTr("Pin to taskbar"),
|
||||
action: () => {
|
||||
TaskbarApps.togglePin(root.appEntry.appId);
|
||||
}
|
||||
},
|
||||
...(root.appEntry.toplevels.length > 0 ? [{
|
||||
iconName: "dismiss",
|
||||
text: root.multiple ? qsTr("Close all windows") : qsTr("Close window"),
|
||||
action: () => {
|
||||
for (let toplevel of root.appEntry.toplevels) {
|
||||
toplevel.close();
|
||||
}
|
||||
}
|
||||
}] : []),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ PopupWindow {
|
||||
property Item anchorItem
|
||||
|
||||
//////////////////// Functions ////////////////////
|
||||
function close() {
|
||||
function close() { // Closing doesn't animate, not sure if they're just lazy or it's intentional
|
||||
marginBehavior.enabled = false;
|
||||
root.visible = false;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ PopupWindow {
|
||||
///////////////////// Internals /////////////////////
|
||||
readonly property bool bottom: Config.options.waffles.bar.bottom
|
||||
property real visualMargin: 12
|
||||
property alias ambientShadowWidth: ambientShadow.border.width
|
||||
property real ambientShadowWidth: 1
|
||||
|
||||
visible: false
|
||||
color: "transparent"
|
||||
@@ -64,16 +64,8 @@ PopupWindow {
|
||||
hoverEnabled: true
|
||||
|
||||
// Shadow
|
||||
Rectangle {
|
||||
id: ambientShadow
|
||||
anchors {
|
||||
fill: contentItem
|
||||
margins: -border.width
|
||||
}
|
||||
border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency)
|
||||
border.width: 1
|
||||
color: "transparent"
|
||||
radius: Looks.radius.large + border.width
|
||||
WAmbientShadow {
|
||||
target: contentItem
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
||||
@@ -17,10 +17,17 @@ MouseArea {
|
||||
previewPopup.show(appEntry, button);
|
||||
}
|
||||
|
||||
Behavior on implicitWidth {
|
||||
animation: Looks.transition.move.createObject(this)
|
||||
}
|
||||
|
||||
// Apps row
|
||||
RowLayout {
|
||||
id: row
|
||||
anchors.fill: parent
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
}
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
@@ -36,6 +43,9 @@ MouseArea {
|
||||
onHoverPreviewRequested: {
|
||||
root.showPreviewPopup(appEntry, this)
|
||||
}
|
||||
onHoverPreviewDismissed: {
|
||||
previewPopup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,4 +56,5 @@ MouseArea {
|
||||
tasksHovered: root.containsMouse
|
||||
anchor.window: root.QsWindow.window
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt.labs.synchronizer
|
||||
import Quickshell
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
property bool overflowOpen: false
|
||||
property bool dragging: false
|
||||
|
||||
Layout.fillHeight: true
|
||||
spacing: 0
|
||||
|
||||
BarIconButton {
|
||||
id: overflowButton
|
||||
|
||||
visible: (TrayService.unpinnedItems.length > 0 || root.dragging)
|
||||
checked: root.overflowOpen
|
||||
|
||||
iconName: "chevron-down"
|
||||
iconMonochrome: true
|
||||
iconRotation: (Config.options.waffles.bar.bottom ? 180 : 0) + (root.overflowOpen ? 180 : 0)
|
||||
Behavior on iconRotation {
|
||||
animation: Looks.transition.rotate.createObject(this)
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.overflowOpen = !root.overflowOpen;
|
||||
}
|
||||
|
||||
TrayOverflowMenu {
|
||||
id: trayOverflowLayout
|
||||
Synchronizer on active {
|
||||
property alias source: root.overflowOpen
|
||||
}
|
||||
}
|
||||
|
||||
BarToolTip {
|
||||
extraVisibleCondition: overflowButton.shouldShowTooltip
|
||||
text: qsTr("Show hidden icons")
|
||||
}
|
||||
|
||||
DropArea {
|
||||
id: pinDropArea
|
||||
anchors.fill: parent
|
||||
property bool willPin: false
|
||||
onEntered: willPin = true
|
||||
onExited: willPin = false
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: TrayService.pinnedItems
|
||||
}
|
||||
delegate: TrayButton {
|
||||
id: trayButton
|
||||
required property var modelData
|
||||
item: modelData
|
||||
|
||||
property real initialX
|
||||
property real initialY
|
||||
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
drag.axis: Drag.XAxis
|
||||
drag.threshold: 2
|
||||
|
||||
onPressed: event => {
|
||||
trayButton.Drag.hotSpot.x = event.x;
|
||||
trayButton.initialX = trayButton.x;
|
||||
root.dragging = true;
|
||||
trayButton.Drag.active = true;
|
||||
}
|
||||
onPositionChanged: {
|
||||
pinTooltip.updateAnchor();
|
||||
}
|
||||
onReleased: {
|
||||
if (!dragArea.drag.active) {
|
||||
trayButton.click();
|
||||
} else {
|
||||
if (pinDropArea.containsDrag && pinDropArea.willPin) {
|
||||
// Quickshell would crash if we don't hide this item first. Took me fucking 3 hours to figure out...
|
||||
trayButton.visible = false;
|
||||
TrayService.togglePin(trayButton.item.id);
|
||||
pinDropArea.willPin = false;
|
||||
} else {
|
||||
trayButton.x = trayButton.initialX;
|
||||
}
|
||||
}
|
||||
trayButton.Drag.active = false;
|
||||
root.dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
BarToolTip {
|
||||
id: pinTooltip
|
||||
extraVisibleCondition: trayButton.Drag.active && pinDropArea.containsDrag && pinDropArea.willPin
|
||||
realContentHorizontalPadding: 6
|
||||
realContentVerticalPadding: 6
|
||||
realContentItem: FluentIcon {
|
||||
anchors.centerIn: parent
|
||||
icon: "pin-off"
|
||||
implicitSize: 18
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Services.SystemTray
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar
|
||||
|
||||
BarIconButton {
|
||||
id: root
|
||||
|
||||
required property SystemTrayItem item
|
||||
property alias menuOpen: menu.visible
|
||||
readonly property bool barAtBottom: Config.options.waffles.bar.bottom
|
||||
iconSource: item.icon
|
||||
iconScale: 0
|
||||
Component.onCompleted: {
|
||||
root.iconScale = 1
|
||||
}
|
||||
Behavior on iconScale {
|
||||
animation: Looks.transition.enter.createObject(this)
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
item.activate();
|
||||
}
|
||||
|
||||
altAction: () => {
|
||||
if (item.hasMenu) menu.open()
|
||||
}
|
||||
|
||||
// This is lazy, but it's not like tray menus on Windoes are consistent...
|
||||
// TODO: Figure out how to do cascading menus then use a custom menu
|
||||
QsMenuAnchor {
|
||||
id: menu
|
||||
menu: root.item.menu
|
||||
anchor {
|
||||
adjustment: PopupAdjustment.ResizeY | PopupAdjustment.SlideX
|
||||
item: root
|
||||
gravity: root.barAtBottom ? Edges.Top : Edges.Bottom
|
||||
edges: root.barAtBottom ? Edges.Top : Edges.Bottom
|
||||
}
|
||||
}
|
||||
|
||||
BarToolTip {
|
||||
extraVisibleCondition: root.shouldShowTooltip && !root.Drag.active
|
||||
text: TrayService.getTooltipForItem(root.item)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
import qs.modules.waffle.bar
|
||||
|
||||
BarPopup {
|
||||
id: root
|
||||
|
||||
closeOnFocusLost: false
|
||||
onFocusCleared: {
|
||||
const hasMenuOpen = contentItem.children.some(c => (c.menuOpen));
|
||||
if (!hasMenuOpen)
|
||||
root.close();
|
||||
else
|
||||
root.grabFocus();
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
id: contentItem
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: contentGrid.implicitWidth
|
||||
implicitHeight: contentGrid.implicitHeight
|
||||
GridLayout {
|
||||
id: contentGrid
|
||||
anchors.centerIn: parent
|
||||
rows: Math.floor(Math.sqrt(TrayService.unpinnedItems.length))
|
||||
columns: Math.ceil(TrayService.unpinnedItems.length / rows)
|
||||
columnSpacing: 0
|
||||
rowSpacing: 0
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: TrayService.unpinnedItems
|
||||
onValuesChanged: {
|
||||
root.updateAnchor();
|
||||
if (values.length === 0) {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate: TrayButton {
|
||||
id: trayButton
|
||||
required property var modelData
|
||||
item: modelData
|
||||
|
||||
topInset: 0
|
||||
bottomInset: 0
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
|
||||
colBackground: ColorUtils.transparentize(Looks.colors.bg2)
|
||||
colBackgroundHover: Looks.colors.bg2Hover
|
||||
colBackgroundActive: Looks.colors.bg2Active
|
||||
|
||||
onMenuOpenChanged: {
|
||||
// The overflow menu should only be closed when the user clicks outside
|
||||
// However the focus grab refuses to reactivate, so we can't have that
|
||||
// But most of the time the user dismisses the menu by clicking outside anyway,
|
||||
// so this is acceptable.
|
||||
if (!menuOpen) {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
property real initialX
|
||||
property real initialY
|
||||
|
||||
Behavior on x {
|
||||
animation: Looks.transition.move.createObject(this)
|
||||
}
|
||||
Behavior on y {
|
||||
animation: Looks.transition.move.createObject(this)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
drag.threshold: 2
|
||||
|
||||
onPressed: event => {
|
||||
trayButton.Drag.hotSpot.x = event.x;
|
||||
trayButton.Drag.hotSpot.y = event.y;
|
||||
trayButton.initialX = trayButton.x;
|
||||
trayButton.initialY = trayButton.y;
|
||||
trayButton.Drag.active = true;
|
||||
}
|
||||
onReleased: {
|
||||
if (!dragArea.drag.active) {
|
||||
trayButton.click();
|
||||
} else {
|
||||
if (!unpinDropArea.containsDrag && unpinDropArea.willUnpin) {
|
||||
// Quickshell would crash if we don't hide this item first. Took me fucking 3 hours to figure out...
|
||||
trayButton.visible = false;
|
||||
TrayService.togglePin(trayButton.item.id);
|
||||
unpinDropArea.willUnpin = false;
|
||||
} else {
|
||||
trayButton.x = trayButton.initialX;
|
||||
trayButton.y = trayButton.initialY;
|
||||
}
|
||||
}
|
||||
trayButton.Drag.active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
id: unpinDropArea
|
||||
anchors.fill: parent
|
||||
property bool willUnpin: false
|
||||
onEntered: willUnpin = false
|
||||
onExited: willUnpin = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import qs.modules.waffle.looks
|
||||
Kirigami.Icon {
|
||||
id: root
|
||||
required property string icon
|
||||
property alias monochrome: root.isMask
|
||||
// Should be 16, but it appears the icons have some padding,
|
||||
// Unlike the Windows-only Segoe UI icons, the open source FluentUI ones are hella small
|
||||
property int implicitSize: 20
|
||||
|
||||
@@ -17,9 +17,12 @@ Singleton {
|
||||
|
||||
property real backgroundTransparency: 0.17
|
||||
property real contentTransparency: 0.25
|
||||
property real shadowTransparency: 0.6
|
||||
colors: QtObject {
|
||||
id: colors
|
||||
property color ambientShadow: ColorUtils.transparentize("#000000", 0.75)
|
||||
property color bgPanelFooter: root.dark ? "#1C1C1C" : "#EEEEEE"
|
||||
property color bgPanelBody: root.dark ? "#242424" : "#F2F2F2"
|
||||
property color bgPanelSeparator: root.dark ? "#191919" : "#E0E0E0"
|
||||
property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
|
||||
property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
|
||||
property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7"
|
||||
@@ -34,6 +37,7 @@ Singleton {
|
||||
property color fg1: root.dark ? "#D1D1D1" : "#626262"
|
||||
property color danger: "#C42B1C"
|
||||
property color dangerActive: "#B62D1F"
|
||||
property color warning: "#FF9900"
|
||||
// property color accent: root.dark ? "#A5C6D8" : "#5377A3"
|
||||
property color accent: Appearance.m3colors.m3primary
|
||||
property color accentUnfocused: root.dark ? "#989898" : "#848484"
|
||||
@@ -61,7 +65,7 @@ Singleton {
|
||||
}
|
||||
property QtObject pixelSize: QtObject {
|
||||
property real normal: 11
|
||||
property real large: 15
|
||||
property real large: 14
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +119,14 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
property Component rotate: Component {
|
||||
NumberAnimation {
|
||||
duration: 170
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeInOut
|
||||
}
|
||||
}
|
||||
|
||||
property Component anchor: Component {
|
||||
AnchorAnimation {
|
||||
duration: 160
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
required property var target
|
||||
z: 0
|
||||
|
||||
anchors {
|
||||
fill: target
|
||||
margins: -border.width
|
||||
}
|
||||
|
||||
border.color: Looks.colors.ambientShadow
|
||||
border.width: 1
|
||||
color: "transparent"
|
||||
radius: target.radius + border.width
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
signal closed()
|
||||
|
||||
property alias border: borderRect
|
||||
required default property Item contentItem
|
||||
property real visualMargin: 12
|
||||
|
||||
function close() {
|
||||
closeAnim.start();
|
||||
}
|
||||
|
||||
readonly property bool barAtBottom: Config.options.waffles.bar.bottom
|
||||
|
||||
implicitHeight: borderRect.implicitHeight
|
||||
implicitWidth: borderRect.implicitWidth
|
||||
|
||||
Rectangle {
|
||||
id: borderRect
|
||||
|
||||
color: "transparent"
|
||||
radius: Looks.radius.large
|
||||
border.color: Looks.colors.bg2Border
|
||||
border.width: 1
|
||||
implicitWidth: contentItem.implicitWidth + border.width * 2
|
||||
implicitHeight: contentItem.implicitHeight + border.width * 2
|
||||
children: [root.contentItem]
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: root.barAtBottom ? undefined : parent.top
|
||||
bottom: root.barAtBottom ? parent.bottom : undefined
|
||||
// Opening anim
|
||||
bottomMargin: root.barAtBottom ? sourceEdgeMargin : 0
|
||||
topMargin: root.barAtBottom ? 0 : sourceEdgeMargin
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
openAnim.start();
|
||||
}
|
||||
|
||||
property real sourceEdgeMargin: -(implicitHeight + root.visualMargin)
|
||||
PropertyAnimation {
|
||||
id: openAnim
|
||||
target: borderRect
|
||||
property: "sourceEdgeMargin"
|
||||
to: 0
|
||||
duration: 200
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
SequentialAnimation {
|
||||
id: closeAnim
|
||||
PropertyAnimation {
|
||||
target: borderRect
|
||||
property: "sourceEdgeMargin"
|
||||
to: -(implicitHeight + root.visualMargin)
|
||||
duration: 150
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
root.closed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
// Generic button with background
|
||||
Button {
|
||||
id: root
|
||||
|
||||
property color colBackgroundHover: Looks.colors.bg2Hover
|
||||
property color colBackgroundActive: Looks.colors.bg2Active
|
||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
||||
|
||||
property alias monochromeIcon: buttonIcon.monochrome
|
||||
property bool forceShowIcon: false
|
||||
|
||||
property var altAction: () => {}
|
||||
property var middleClickAction: () => {}
|
||||
|
||||
property real inset: 2
|
||||
topInset: inset
|
||||
bottomInset: inset
|
||||
leftInset: inset
|
||||
rightInset: inset
|
||||
horizontalPadding: 10
|
||||
verticalPadding: 6
|
||||
implicitHeight: contentItem.implicitHeight + verticalPadding * 2
|
||||
implicitWidth: contentItem.implicitWidth + horizontalPadding * 2
|
||||
|
||||
background: Rectangle {
|
||||
radius: Looks.radius.medium
|
||||
color: {
|
||||
if (root.down) {
|
||||
return root.colBackgroundActive;
|
||||
} else if ((root.hovered && !root.down) || root.checked) {
|
||||
return root.colBackgroundHover;
|
||||
} else {
|
||||
return root.colBackground;
|
||||
}
|
||||
}
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: (event) => {
|
||||
if (event.button === Qt.LeftButton) root.clicked();
|
||||
if (event.button === Qt.RightButton) root.altAction();
|
||||
if (event.button === Qt.MiddleButton) root.middleClickAction();
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: root.inset
|
||||
}
|
||||
implicitWidth: contentLayout.implicitWidth
|
||||
implicitHeight: contentLayout.implicitHeight
|
||||
RowLayout {
|
||||
id: contentLayout
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: root.horizontalPadding
|
||||
rightMargin: root.horizontalPadding
|
||||
}
|
||||
spacing: 12
|
||||
FluentIcon {
|
||||
id: buttonIcon
|
||||
visible: root.icon.name !== "" || root.forceShowIcon
|
||||
monochrome: true
|
||||
implicitSize: 16
|
||||
Layout.leftMargin: 6
|
||||
Layout.fillWidth: false
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon: root.icon.name
|
||||
}
|
||||
WText {
|
||||
Layout.rightMargin: 12
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
text: root.text
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font {
|
||||
pixelSize: Looks.font.pixelSize.large
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Button {
|
||||
id: root
|
||||
|
||||
implicitHeight: 36
|
||||
|
||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
||||
property color colBackgroundHover: Looks.colors.bg1Hover
|
||||
property color colBackgroundActive: Looks.colors.bg1Active
|
||||
property color color
|
||||
property color colForeground: Looks.colors.fg
|
||||
color: {
|
||||
if (root.down) {
|
||||
return root.colBackgroundActive
|
||||
} else if ((root.hovered && !root.down) || root.checked) {
|
||||
return root.colBackgroundHover
|
||||
} else {
|
||||
return root.colBackground
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
radius: Looks.radius.medium
|
||||
color: root.color
|
||||
}
|
||||
}
|
||||
@@ -10,42 +10,37 @@ import qs.modules.waffle.looks
|
||||
PopupToolTip {
|
||||
id: root
|
||||
|
||||
property real padding: 2
|
||||
verticalPadding: padding
|
||||
horizontalPadding: padding
|
||||
property Item realContentItem
|
||||
realContentItem: WText {
|
||||
text: root.text
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
property real visualMargin: 11
|
||||
verticalPadding: visualMargin
|
||||
horizontalPadding: visualMargin
|
||||
property real realContentVerticalPadding: 8
|
||||
property real realContentHorizontalPadding: 10
|
||||
|
||||
contentItem: Item {
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: realContent.implicitWidth + root.verticalPadding * 2
|
||||
implicitHeight: realContent.implicitHeight + root.horizontalPadding * 2
|
||||
implicitWidth: realContent.implicitWidth + 2 * 2
|
||||
implicitHeight: realContent.implicitHeight + 2 * 2
|
||||
|
||||
Rectangle {
|
||||
id: ambientShadow
|
||||
z: 0
|
||||
anchors {
|
||||
fill: realContent
|
||||
margins: -border.width
|
||||
}
|
||||
border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency)
|
||||
border.width: 1
|
||||
color: "transparent"
|
||||
radius: realContent.radius + border.width
|
||||
WAmbientShadow {
|
||||
target: realContent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: realContent
|
||||
z: 1
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: tooltipText.implicitWidth + 10 * 2
|
||||
implicitHeight: tooltipText.implicitHeight + 8 * 2
|
||||
implicitWidth: root.realContentItem.implicitWidth + root.realContentHorizontalPadding * 2
|
||||
implicitHeight: root.realContentItem.implicitHeight + root.realContentVerticalPadding * 2
|
||||
color: Looks.colors.bg1
|
||||
radius: Looks.radius.medium
|
||||
|
||||
WText {
|
||||
id: tooltipText
|
||||
text: root.text
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
children: [root.realContentItem]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,10 +135,18 @@ Singleton {
|
||||
}
|
||||
|
||||
function syncBrightness() {
|
||||
const brightnessValue = Math.max(monitor.multipliedBrightness, 0)
|
||||
const rawValueRounded = Math.max(Math.floor(brightnessValue * monitor.rawMaxBrightness), 1);
|
||||
setProc.command = isDdc ? ["ddcutil", "-b", busNum, "setvcp", "10", rawValueRounded] : ["brightnessctl", "--class", "backlight", "s", rawValueRounded, "--quiet"];
|
||||
setProc.startDetached();
|
||||
const brightnessValue = Math.max(monitor.multipliedBrightness, 0);
|
||||
if (isDdc) {
|
||||
const rawValueRounded = Math.max(Math.floor(brightnessValue * monitor.rawMaxBrightness), 1);
|
||||
setProc.command = ["ddcutil", "-b", busNum, "setvcp", "10", rawValueRounded];
|
||||
setProc.startDetached();
|
||||
} else {
|
||||
const valuePercentNumber = Math.floor(brightnessValue * 100);
|
||||
let valuePercent = `${valuePercentNumber}%`;
|
||||
if (valuePercentNumber == 0) valuePercent = "1"; // Prevent fully black
|
||||
setProc.command = ["brightnessctl", "--class", "backlight", "s", valuePercent, "--quiet"];
|
||||
setProc.startDetached();
|
||||
}
|
||||
}
|
||||
|
||||
function setBrightness(value: real): void {
|
||||
|
||||
@@ -30,7 +30,7 @@ Singleton {
|
||||
|
||||
function enable() {
|
||||
root.active = true
|
||||
Quickshell.execDetached(["bash", "-c", "easyeffects --gapplication-service || flatpak run com.github.wwmm.easyeffects --gapplication-service"])
|
||||
Quickshell.execDetached(["bash", "-c", "easyeffects --hide-window --service-mode || flatpak run com.github.wwmm.easyeffects --hide-window --service-mode"])
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
|
||||
@@ -58,6 +58,7 @@ Singleton {
|
||||
|
||||
// Update the distroIcon property based on distroId
|
||||
switch (distroId) {
|
||||
case "artix":
|
||||
case "arch": distroIcon = "arch-symbolic"; break;
|
||||
case "endeavouros": distroIcon = "endeavouros-symbolic"; break;
|
||||
case "cachyos": distroIcon = "cachyos-symbolic"; break;
|
||||
|
||||
@@ -8,6 +8,14 @@ import Quickshell.Wayland
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
function togglePin(appId) {
|
||||
if (Config.options.dock.pinnedApps.indexOf(appId) !== -1) {
|
||||
Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.filter(id => id !== appId)
|
||||
} else {
|
||||
Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.concat([appId])
|
||||
}
|
||||
}
|
||||
|
||||
property list<var> apps: {
|
||||
var map = new Map();
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
pragma Singleton
|
||||
|
||||
import qs.modules.common
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Services.SystemTray
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property bool smartTray: Config.options.tray.filterPassive
|
||||
property list<var> itemsInUserList: SystemTray.items.values.filter(i => (Config.options.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
|
||||
property list<var> itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
|
||||
|
||||
property bool invertPins: Config.options.tray.invertPinnedItems
|
||||
property list<var> pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList
|
||||
property list<var> unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList
|
||||
|
||||
function getTooltipForItem(item) {
|
||||
var result = item.tooltipTitle.length > 0 ? item.tooltipTitle
|
||||
: (item.title.length > 0 ? item.title : item.id);
|
||||
if (item.tooltipDescription.length > 0) result += " • " + item.tooltipDescription;
|
||||
if (Config.options.tray.showItemId) result += "\n[" + item.id + "]";
|
||||
return result;
|
||||
}
|
||||
|
||||
// Pinning
|
||||
function pin(itemId) {
|
||||
var pins = Config.options.tray.pinnedItems;
|
||||
if (pins.includes(itemId)) return;
|
||||
Config.options.tray.pinnedItems.push(itemId);
|
||||
}
|
||||
function unpin(itemId) {
|
||||
Config.options.tray.pinnedItems = Config.options.tray.pinnedItems.filter(id => id !== itemId);
|
||||
}
|
||||
function togglePin(itemId) {
|
||||
var pins = Config.options.tray.pinnedItems;
|
||||
if (pins.includes(itemId)) {
|
||||
unpin(itemId)
|
||||
} else {
|
||||
pin(itemId)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
pragma Singleton
|
||||
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
/*
|
||||
* System updates service. Currently only supports Arch.
|
||||
*/
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property bool available: false
|
||||
property int count: 0
|
||||
|
||||
readonly property bool updateAdvised: available && count > Config.options.updates.adviseUpdateThreshold
|
||||
readonly property bool updateStronglyAdvised: available && count > Config.options.updates.stronglyAdviseUpdateThreshold
|
||||
|
||||
function load() {}
|
||||
function refresh() {
|
||||
if (!available) return;
|
||||
print("[Updates] Checking for system updates")
|
||||
checkUpdatesProc.running = true;
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: Config.options.updates.checkInterval * 60 * 1000
|
||||
repeat: true
|
||||
running: Config.ready
|
||||
onTriggered: {
|
||||
print("[Updates] Periodic update check due")
|
||||
root.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: checkAvailabilityProc
|
||||
running: true
|
||||
command: ["which", "checkupdates"]
|
||||
onExited: (exitCode, exitStatus) => {
|
||||
root.available = (exitCode === 0);
|
||||
root.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: checkUpdatesProc
|
||||
command: ["bash", "-c", "checkupdates | wc -l"]
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
root.count = parseInt(text.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import qs.modules.ii.overlay
|
||||
import qs.modules.ii.verticalBar
|
||||
import qs.modules.ii.wallpaperSelector
|
||||
|
||||
import qs.modules.waffle.actionCenter
|
||||
import qs.modules.waffle.background
|
||||
import qs.modules.waffle.bar
|
||||
|
||||
@@ -49,6 +50,7 @@ ShellRoot {
|
||||
ConflictKiller.load()
|
||||
Cliphist.refresh()
|
||||
Wallpapers.load()
|
||||
Updates.load()
|
||||
}
|
||||
|
||||
// Load enabled stuff
|
||||
@@ -74,6 +76,7 @@ ShellRoot {
|
||||
PanelLoader { identifier: "iiSidebarRight"; component: SidebarRight {} }
|
||||
PanelLoader { identifier: "iiVerticalBar"; extraCondition: Config.options.bar.vertical; component: VerticalBar {} }
|
||||
PanelLoader { identifier: "iiWallpaperSelector"; component: WallpaperSelector {} }
|
||||
PanelLoader { identifier: "wActionCenter"; component: WaffleActionCenter {} }
|
||||
PanelLoader { identifier: "wBar"; component: WaffleBar {} }
|
||||
PanelLoader { identifier: "wBackground"; component: WaffleBackground {} }
|
||||
|
||||
@@ -87,7 +90,7 @@ ShellRoot {
|
||||
property list<string> families: ["ii", "waffle"]
|
||||
property var panelFamilies: ({
|
||||
"ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"],
|
||||
"waffle": ["wBar", "wBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiWallpaperSelector"],
|
||||
"waffle": ["wBar", "wBackground", "wActionCenter", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarRight", "iiWallpaperSelector"],
|
||||
})
|
||||
function cyclePanelFamily() {
|
||||
const currentIndex = families.indexOf(Config.options.panelFamily)
|
||||
|
||||
@@ -211,6 +211,7 @@ Extra dependencies.
|
||||
- `qt6-translations`
|
||||
- `qt6-virtualkeyboard`
|
||||
- `qt6-wayland`
|
||||
- `kirigami`
|
||||
- `kdialog`
|
||||
- `syntax-highlighting`
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ conflicts=("quickshell-git")
|
||||
_pkgname=quickshell
|
||||
pkgname="$_prefix-$_pkgname-git"
|
||||
pkgver=0.1.0.r1
|
||||
pkgrel=5
|
||||
pkgrel=6
|
||||
pkgdesc="$_pkgname-git pinned commit and extra deps for $_prefix"
|
||||
arch=(x86_64 aarch64)
|
||||
url='https://git.outfoxxed.me/quickshell/quickshell'
|
||||
@@ -39,6 +39,7 @@ depends=(
|
||||
qt6-translations
|
||||
qt6-virtualkeyboard
|
||||
qt6-wayland
|
||||
kirigami
|
||||
kdialog
|
||||
syntax-highlighting
|
||||
)
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
Name: Bibata-Modern-Classic
|
||||
Version: 2.0.7
|
||||
Release: %autorelease
|
||||
Summary: Open source, compact, and material designed cursor set.
|
||||
|
||||
License: GPL-3.0
|
||||
URL: https://github.com/ful1e5/Bibata_Cursor
|
||||
Source0: %{name}.tar.xz
|
||||
|
||||
BuildArch: noarch
|
||||
|
||||
%description
|
||||
Open source, compact, and material designed cursor set.
|
||||
|
||||
%prep
|
||||
wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/v%{version}/Bibata-Modern-Classic.tar.xz
|
||||
wget -q -O %{_buildrootdir}/LICENSE %{url}/raw/refs/heads/main/LICENSE
|
||||
%setup -q -n %{name}
|
||||
|
||||
%build
|
||||
:
|
||||
|
||||
%install
|
||||
install -d -m 0755 %{buildroot}%{_iconsdir}/Bibata-Modern-Classic
|
||||
cp -r * %{buildroot}%{_iconsdir}/Bibata-Modern-Classic
|
||||
|
||||
install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
|
||||
install -m 0644 %{_buildrootdir}/LICENSE %{buildroot}%{_licensedir}/%{name}/
|
||||
|
||||
%files
|
||||
%{_iconsdir}/Bibata-Modern-Classic
|
||||
%license %{_licensedir}/%{name}/LICENSE
|
||||
|
||||
%changelog
|
||||
%autochangelog
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
Name: JetBrainsMonoNerdFont-Regular
|
||||
Version: 1.2
|
||||
Release: %autorelease
|
||||
Summary: JetBrainsMonoNerdFonts (TrueType Outlines) (Regulear)
|
||||
|
||||
License: MIT
|
||||
URL: https://github.com/Zhaopudark/JetBrainsMonoNerdFonts
|
||||
Source0: %{name}
|
||||
|
||||
BuildRequires: fonts-rpm-macros
|
||||
BuildArch: noarch
|
||||
|
||||
%description
|
||||
An auto-updated compiling version of JetBrains Mono that has been patched with Nerd Fonts.
|
||||
|
||||
%prep
|
||||
wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/v%{version}/JetBrainsMonoNerdFont-Regular-v%{version}.ttf
|
||||
wget -q -P %{_sourcedir} %{url}/raw/refs/heads/main/LICENSE
|
||||
|
||||
%build
|
||||
:
|
||||
|
||||
%install
|
||||
install -d -m 0755 %{buildroot}%{_fontdir}
|
||||
install -m 0644 %{_sourcedir}/JetBrainsMonoNerdFont*ttf %{buildroot}%{_fontdir}
|
||||
|
||||
install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
|
||||
install -m 0644 %{_sourcedir}/LICENSE %{buildroot}%{_licensedir}/%{name}/
|
||||
|
||||
%post
|
||||
/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
|
||||
|
||||
%postun
|
||||
/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
|
||||
|
||||
%files
|
||||
%{_fontdir}/JetBrainsMonoNerdFont*ttf
|
||||
%license %{_licensedir}/%{name}/LICENSE
|
||||
|
||||
%changelog
|
||||
%autochangelog
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
%global commit0 0e3707f6dafebb121d98b53c64364d16fefe481d
|
||||
%global shortcommit0 %(c=%{commit0}; echo ${c:0:7})
|
||||
%global bumpver 100
|
||||
|
||||
Name: MicroTeX
|
||||
Version: 0.0.1%{?bumpver:^%{bumpver}.git%{shortcommit0}}
|
||||
Release: %autorelease
|
||||
Summary: A dynamic, cross-platform, and embeddable LaTeX rendering library
|
||||
|
||||
License: MIT
|
||||
URL: https://github.com/NanoMichael/MicroTeX
|
||||
Source0: %{name}-%{shortcommit0}.tar.gz
|
||||
|
||||
BuildRequires: gcc-c++ cmake
|
||||
BuildRequires: pkgconfig(tinyxml2)
|
||||
BuildRequires: gtkmm3.0-devel gtksourceviewmm3-devel cairomm-devel
|
||||
|
||||
%description
|
||||
MicroTeX is a library for rendering LaTeX mathematical formulas, supporting multiple backends
|
||||
such as GTK+, Qt, and Skia. It provides both library components and demo applications for
|
||||
testing LaTeX rendering.
|
||||
|
||||
%prep
|
||||
curl -fsSL --retry 3 \
|
||||
https://codeload.github.com/NanoMichael/MicroTeX/tar.gz/%{shortcommit0} \
|
||||
-o %{_sourcedir}/%{name}-%{shortcommit0}.tar.gz
|
||||
%setup -q -n %{name}-%{shortcommit0}
|
||||
|
||||
%build
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j$(nproc)
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/opt/MicroTeX
|
||||
cp build/LaTeX %{buildroot}/opt/MicroTeX/
|
||||
cp -r build/res %{buildroot}/opt/MicroTeX/
|
||||
|
||||
install -Dpm 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE
|
||||
install -Dpm 0644 res/greek/LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE-greek
|
||||
install -Dpm 0644 res/cyrillic/LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE-cyrillic
|
||||
|
||||
%files
|
||||
/opt/MicroTeX/
|
||||
%license %{_licensedir}/%{name}/
|
||||
|
||||
%changelog
|
||||
%autochangelog
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
Name: breeze-plus
|
||||
Version: 6.19.0
|
||||
Release: %autorelease
|
||||
Summary: Breeze theme with additional icons
|
||||
|
||||
License: LGPL-2.1
|
||||
URL: https://github.com/mjkim0727/breeze-plus
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
|
||||
BuildArch: noarch
|
||||
|
||||
%description
|
||||
Breeze icon theme with additional icons for applications not covered by the
|
||||
official Breeze theme. Includes icons for Wine, third-party apps, and more.
|
||||
|
||||
%prep
|
||||
wget --content-disposition -q -N -P %{_sourcedir} %{url}/archive/refs/tags/%{version}.tar.gz
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
:
|
||||
|
||||
%install
|
||||
install -d -m 0755 %{buildroot}%{_iconsdir}/breeze-plus
|
||||
cp -r src/breeze-plus %{buildroot}%{_iconsdir}/
|
||||
cp -r src/breeze-plus-dark %{buildroot}%{_iconsdir}/
|
||||
|
||||
install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
|
||||
install -m 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/
|
||||
|
||||
%files
|
||||
%{_iconsdir}/breeze-plus/
|
||||
%{_iconsdir}/breeze-plus-dark/
|
||||
%license %{_licensedir}/%{name}/LICENSE
|
||||
|
||||
%changelog
|
||||
%autochangelog
|
||||
|
||||