137 Commits
Author SHA1 Message Date
zach 4f544981c1 delete unknown json objects + write missing objects to config file 2026-08-16 12:17:50 +02:00
zach 02bb7e43d8 Merge pull request 'Feat: Reposition bar' (#147) from feat/reposition-bar into main
Reviewed-on: #147
Reviewed-by: AramJonghu <aramjonghu@tutamail.com>
2026-08-16 11:02:22 +02:00
zach fb0c75a2ba remove debug logging
C++ / fmt (pull_request) Successful in 8s
JS/TS / fmt (pull_request) Successful in 11s
JS/TS / lint (pull_request) Successful in 15s
Python / fmt (pull_request) Successful in 24s
Python / lint (pull_request) Successful in 25s
Python / test (pull_request) Successful in 48s
Python / typecheck (pull_request) Successful in 1m1s
Rust / fmt (pull_request) Successful in 34s
Rust / build (pull_request) Successful in 1m45s
C++ / build (pull_request) Successful in 4m18s
Python / buildcheck (pull_request) Successful in 2m20s
Rust / clippy (pull_request) Successful in 1m1s
C++ / clang-tidy (pull_request) Successful in 5m23s
2026-08-15 19:38:33 +02:00
zach 5efa0de3a5 WidgetBase for bar widget + fixed resources and dashboard popouts in left- and bottom-edge bar
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 17s
JS/TS / lint (pull_request) Successful in 20s
Python / fmt (pull_request) Successful in 31s
Python / lint (pull_request) Successful in 30s
Python / test (pull_request) Successful in 1m40s
Python / typecheck (pull_request) Successful in 1m38s
C++ / build (pull_request) Successful in 2m15s
Rust / build (pull_request) Successful in 1m41s
Rust / fmt (pull_request) Successful in 59s
Python / buildcheck (pull_request) Successful in 2m40s
Rust / clippy (pull_request) Successful in 2m15s
C++ / clang-tidy (pull_request) Successful in 6m29s
2026-08-15 19:37:44 +02:00
zach 858ef68565 Merge branch 'main' into feat/reposition-bar
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 21s
JS/TS / lint (pull_request) Successful in 22s
Python / lint (pull_request) Successful in 31s
Python / fmt (pull_request) Successful in 34s
Python / test (pull_request) Successful in 59s
Python / typecheck (pull_request) Successful in 1m22s
Rust / fmt (pull_request) Successful in 34s
Rust / build (pull_request) Successful in 1m46s
C++ / build (pull_request) Successful in 2m33s
Rust / clippy (pull_request) Successful in 1m5s
Python / buildcheck (pull_request) Successful in 2m29s
C++ / clang-tidy (pull_request) Successful in 3m56s
2026-08-15 18:04:14 +02:00
zach 5e97ea6867 Merge pull request 'CI: typecheck fixes include dependencies + arch Dockerfile build fix' (#148) from fix/cli-typecheck into main
Reviewed-on: #148
Reviewed-by: zach <zach@brohn.se>
2026-08-15 18:03:54 +02:00
zach 9823c66299 restructure bar components layout
C++ / fmt (pull_request) Successful in 4s
JS/TS / lint (pull_request) Successful in 19s
JS/TS / fmt (pull_request) Successful in 21s
Python / fmt (pull_request) Successful in 30s
Python / lint (pull_request) Successful in 31s
Python / test (pull_request) Successful in 1m2s
Python / typecheck (pull_request) Failing after 1m5s
Rust / fmt (pull_request) Successful in 43s
C++ / build (pull_request) Successful in 2m25s
Rust / build (pull_request) Successful in 1m42s
Python / buildcheck (pull_request) Successful in 2m27s
Rust / clippy (pull_request) Successful in 1m29s
C++ / clang-tidy (pull_request) Successful in 3m56s
2026-08-15 14:18:00 +02:00
zach 0092b41a05 fix config file writing + positioning issues
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 22s
JS/TS / lint (pull_request) Successful in 27s
Python / fmt (pull_request) Successful in 33s
Python / lint (pull_request) Successful in 32s
Python / test (pull_request) Successful in 1m3s
Python / typecheck (pull_request) Failing after 1m4s
Rust / fmt (pull_request) Successful in 41s
Rust / build (pull_request) Successful in 1m39s
C++ / build (pull_request) Successful in 2m33s
Rust / clippy (pull_request) Successful in 1m18s
Python / buildcheck (pull_request) Successful in 2m23s
C++ / clang-tidy (pull_request) Successful in 3m56s
2026-08-14 22:15:11 +02:00
AramJonghu abf7382771 ci: libcava dev headers
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 12s
JS/TS / lint (pull_request) Successful in 16s
Python / lint (pull_request) Successful in 33s
Python / fmt (pull_request) Successful in 36s
Python / test (pull_request) Successful in 1m3s
Python / typecheck (pull_request) Successful in 1m21s
Rust / fmt (pull_request) Successful in 33s
C++ / build (pull_request) Successful in 2m26s
Rust / build (pull_request) Successful in 1m43s
Python / buildcheck (pull_request) Successful in 2m12s
Rust / clippy (pull_request) Successful in 1m41s
C++ / clang-tidy (pull_request) Successful in 4m10s
2026-08-14 20:00:27 +02:00
AramJonghu a1a8a6e695 ci: add relevant dependencies; resolves MissingImport
C++ / fmt (pull_request) Successful in 4s
JS/TS / lint (pull_request) Successful in 15s
JS/TS / fmt (pull_request) Successful in 21s
Python / fmt (pull_request) Successful in 31s
Python / lint (pull_request) Successful in 34s
Python / test (pull_request) Successful in 1m0s
Python / typecheck (pull_request) Successful in 1m20s
Rust / fmt (pull_request) Successful in 34s
C++ / build (pull_request) Successful in 2m29s
Rust / build (pull_request) Successful in 1m45s
Rust / clippy (pull_request) Successful in 1m2s
Python / buildcheck (pull_request) Successful in 2m18s
C++ / clang-tidy (pull_request) Successful in 3m52s
2026-08-14 19:40:28 +02:00
zach abef1eb259 Merge branch 'main' into feat/reposition-bar
C++ / fmt (pull_request) Successful in 4s
JS/TS / lint (pull_request) Successful in 16s
JS/TS / fmt (pull_request) Successful in 23s
Python / fmt (pull_request) Successful in 33s
Python / lint (pull_request) Successful in 32s
Python / test (pull_request) Successful in 1m0s
Python / typecheck (pull_request) Failing after 1m8s
Rust / fmt (pull_request) Successful in 34s
Rust / build (pull_request) Successful in 1m46s
C++ / build (pull_request) Successful in 2m33s
Rust / clippy (pull_request) Successful in 1m30s
Python / buildcheck (pull_request) Successful in 2m41s
C++ / clang-tidy (pull_request) Successful in 7m9s
2026-08-14 19:16:01 +02:00
zach 6c80862ce8 Merge pull request 'Rewrite shell configuration options as well as read/write functionality as plugin' (#143) from refactor/config-rw-plugin into main
Reviewed-on: #143
Reviewed-by: AramJonghu <aramjonghu@tutamail.com>
2026-08-14 18:54:32 +02:00
zach 97ecf68b46 add file+dir watcher & gatekeep reloads
C++ / fmt (pull_request) Successful in 5s
JS/TS / lint (pull_request) Successful in 21s
JS/TS / fmt (pull_request) Successful in 20s
Python / lint (pull_request) Successful in 32s
Python / fmt (pull_request) Successful in 34s
Python / test (pull_request) Successful in 58s
Python / typecheck (pull_request) Failing after 58s
Rust / fmt (pull_request) Successful in 43s
Rust / build (pull_request) Successful in 1m48s
C++ / build (pull_request) Successful in 2m36s
Rust / clippy (pull_request) Successful in 1m18s
Python / buildcheck (pull_request) Successful in 2m21s
C++ / clang-tidy (pull_request) Successful in 3m54s
2026-08-14 18:40:50 +02:00
zach ef8811724f better height/width for bar
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 19s
Python / lint (pull_request) Successful in 30s
Python / fmt (pull_request) Successful in 34s
Python / test (pull_request) Successful in 1m0s
Python / typecheck (pull_request) Failing after 1m18s
C++ / build (pull_request) Successful in 1m49s
Rust / fmt (pull_request) Successful in 33s
Rust / build (pull_request) Successful in 1m33s
Rust / clippy (pull_request) Successful in 1m17s
Python / buildcheck (pull_request) Successful in 2m40s
C++ / clang-tidy (pull_request) Successful in 3m25s
2026-08-14 18:03:56 +02:00
zach 4517e5ecd0 left-bar working, bottom bar semi-broken 2026-08-14 16:31:52 +02:00
zach bda2c3821e fix resources colors
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 18s
Python / fmt (pull_request) Successful in 33s
Python / lint (pull_request) Successful in 31s
Python / test (pull_request) Successful in 1m4s
Python / typecheck (pull_request) Failing after 1m14s
Rust / fmt (pull_request) Successful in 37s
Rust / build (pull_request) Successful in 1m47s
C++ / build (pull_request) Successful in 2m39s
Rust / clippy (pull_request) Successful in 1m10s
Python / buildcheck (pull_request) Successful in 2m27s
C++ / clang-tidy (pull_request) Successful in 3m55s
2026-08-13 21:43:28 +02:00
zach 6ec58cb73a remove debug statelayer
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 11s
JS/TS / lint (pull_request) Successful in 23s
Python / fmt (pull_request) Successful in 30s
Python / lint (pull_request) Successful in 32s
Python / test (pull_request) Successful in 59s
Python / typecheck (pull_request) Failing after 1m0s
Rust / fmt (pull_request) Successful in 45s
C++ / build (pull_request) Successful in 2m31s
Rust / build (pull_request) Successful in 1m49s
Rust / clippy (pull_request) Successful in 1m17s
Python / buildcheck (pull_request) Successful in 2m25s
C++ / clang-tidy (pull_request) Successful in 3m56s
2026-08-13 21:26:48 +02:00
zach 501e866a68 fix font & greeter bin
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 26s
JS/TS / lint (pull_request) Successful in 29s
Python / lint (pull_request) Successful in 33s
Python / fmt (pull_request) Successful in 35s
Python / test (pull_request) Successful in 58s
Python / typecheck (pull_request) Failing after 1m8s
Rust / fmt (pull_request) Successful in 46s
C++ / build (pull_request) Successful in 2m22s
Rust / build (pull_request) Successful in 1m31s
Python / buildcheck (pull_request) Successful in 2m18s
Rust / clippy (pull_request) Successful in 1m26s
C++ / clang-tidy (pull_request) Successful in 3m55s
2026-08-13 21:22:21 +02:00
zach 566ccd67d9 fix greeter start script
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 21s
JS/TS / lint (pull_request) Successful in 23s
Python / fmt (pull_request) Successful in 34s
Python / lint (pull_request) Successful in 33s
Python / test (pull_request) Successful in 1m0s
Python / typecheck (pull_request) Failing after 1m5s
Rust / fmt (pull_request) Successful in 37s
Rust / build (pull_request) Successful in 1m46s
C++ / build (pull_request) Successful in 2m40s
Rust / clippy (pull_request) Successful in 1m15s
Python / buildcheck (pull_request) Successful in 2m28s
C++ / clang-tidy (pull_request) Successful in 3m57s
2026-08-13 15:54:41 +02:00
zach b2e092d0be changes to config plugin, reduce file amount + code, fix greeter 2026-08-13 15:41:16 +02:00
zach 9d2f78eb5e fix cmake take 2 2026-08-13 02:30:56 +02:00
zach 3a4ee148bf fix cmake 2026-08-13 02:29:46 +02:00
zach 3cd3209b28 config moved to c++ plugin, removed old qml + fileview implementation 2026-08-13 02:25:26 +02:00
zach 1d150292d3 initial commit for repositioning bar, currently broken 2026-08-12 20:15:55 +02:00
zach c29b91cd26 Merge pull request 'Screenshot tools features' (#141) from screenshot-picker-improvements into main
Reviewed-on: #141
Reviewed-by: Inorishio <inorishio@gmail.com>
2026-08-11 21:59:32 +02:00
zach 06fb202e36 ctrl + c & ctrl + s shortcuts + screenshot destination dir env var
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 17s
Python / fmt (pull_request) Successful in 32s
Python / lint (pull_request) Successful in 32s
Python / test (pull_request) Successful in 1m0s
C++ / build (pull_request) Successful in 1m35s
Python / typecheck (pull_request) Failing after 1m12s
Rust / fmt (pull_request) Successful in 38s
Rust / build (pull_request) Successful in 1m34s
Rust / clippy (pull_request) Successful in 1m28s
Python / buildcheck (pull_request) Successful in 2m35s
C++ / clang-tidy (pull_request) Successful in 3m23s
2026-08-11 18:57:36 +02:00
zach ad5fda2718 Merge branch 'main' into screenshot-picker-improvements
C++ / fmt (pull_request) Successful in 7s
JS/TS / fmt (pull_request) Successful in 13s
JS/TS / lint (pull_request) Successful in 15s
Python / fmt (pull_request) Successful in 29s
Python / lint (pull_request) Successful in 27s
Python / test (pull_request) Successful in 50s
Python / typecheck (pull_request) Failing after 48s
Rust / fmt (pull_request) Successful in 38s
C++ / build (pull_request) Successful in 3m0s
Rust / build (pull_request) Successful in 1m40s
Python / buildcheck (pull_request) Successful in 2m26s
Rust / clippy (pull_request) Successful in 1m15s
C++ / clang-tidy (pull_request) Successful in 4m27s
2026-08-11 15:03:12 +02:00
zach 7482741e46 Merge pull request 'Status icons' (#142) from refactor/status-icons into main
Reviewed-on: #142
2026-08-11 15:03:04 +02:00
zach 2e4517b0a6 simpler model for status entries
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 16s
Python / fmt (pull_request) Successful in 29s
Python / lint (pull_request) Successful in 30s
Python / test (pull_request) Successful in 59s
Python / typecheck (pull_request) Failing after 1m7s
C++ / build (pull_request) Successful in 1m51s
Rust / fmt (pull_request) Successful in 40s
Rust / build (pull_request) Successful in 1m36s
Python / buildcheck (pull_request) Successful in 2m26s
Rust / clippy (pull_request) Successful in 1m42s
C++ / clang-tidy (pull_request) Successful in 5m31s
2026-08-11 15:00:44 +02:00
zach d81808dd8f refactor: use entries directly in bar object instead of nested components + various fixes and additions to settings
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 11s
JS/TS / lint (pull_request) Successful in 23s
Python / lint (pull_request) Successful in 30s
Python / fmt (pull_request) Successful in 32s
Python / test (pull_request) Successful in 1m1s
Python / typecheck (pull_request) Failing after 52s
C++ / build (pull_request) Successful in 1m45s
Rust / fmt (pull_request) Successful in 57s
Rust / build (pull_request) Successful in 1m50s
Rust / clippy (pull_request) Successful in 1m44s
Python / buildcheck (pull_request) Successful in 2m29s
C++ / clang-tidy (pull_request) Successful in 3m31s
2026-08-11 14:05:57 +02:00
zach 47c842941f screenshot tools baked-in: drawing uses optimized qcanvaspainter, direct to clipboard, eliminate forking to swappy
C++ / fmt (pull_request) Successful in 7s
JS/TS / lint (pull_request) Successful in 21s
JS/TS / fmt (pull_request) Successful in 20s
Python / lint (pull_request) Successful in 31s
Python / fmt (pull_request) Successful in 33s
Python / typecheck (pull_request) Failing after 1m4s
Python / test (pull_request) Successful in 1m7s
C++ / build (pull_request) Successful in 1m48s
Rust / fmt (pull_request) Successful in 37s
Rust / build (pull_request) Successful in 1m42s
Python / buildcheck (pull_request) Successful in 2m33s
Rust / clippy (pull_request) Successful in 1m32s
C++ / clang-tidy (pull_request) Successful in 3m35s
2026-08-10 12:02:34 +02:00
zach 93c6ac251e Merge pull request 'pr and issue templates + typecheck ci python' (#138) from 135-issue-pr-templates into main
Reviewed-on: #138
Reviewed-by: zach <zach@brohn.se>
2026-07-10 18:19:23 +02:00
zach 1af6bf33ff Merge branch 'main' into 135-issue-pr-templates
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 17s
JS/TS / lint (pull_request) Successful in 22s
Python / lint (pull_request) Successful in 31s
Python / fmt (pull_request) Successful in 34s
Python / test (pull_request) Successful in 59s
Python / typecheck (pull_request) Failing after 59s
C++ / build (pull_request) Successful in 2m4s
Rust / fmt (pull_request) Successful in 1m0s
Rust / build (pull_request) Successful in 1m53s
Python / buildcheck (pull_request) Successful in 2m41s
Rust / clippy (pull_request) Successful in 2m31s
C++ / clang-tidy (pull_request) Successful in 6m12s
2026-07-10 15:21:24 +02:00
zach 5eaebacbab remove unrelated directory 2026-07-10 15:00:02 +02:00
AramJonghu 4cb30647a9 hotfix(bugreport): adding optional input field; which init system?
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 15s
Python / lint (pull_request) Successful in 32s
Python / fmt (pull_request) Successful in 35s
Python / test (pull_request) Successful in 1m8s
Python / typecheck (pull_request) Failing after 1m10s
C++ / build (pull_request) Successful in 1m41s
Rust / build (pull_request) Successful in 1m44s
Rust / fmt (pull_request) Successful in 1m5s
Python / buildcheck (pull_request) Successful in 2m39s
Rust / clippy (pull_request) Successful in 2m3s
C++ / clang-tidy (pull_request) Successful in 3m42s
2026-07-10 12:07:27 +02:00
AramJonghu b3820ce1e0 Merge branch 'main' into 135-issue-pr-templates
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 17s
Python / fmt (pull_request) Successful in 35s
Python / lint (pull_request) Successful in 32s
Python / typecheck (pull_request) Failing after 55s
Python / test (pull_request) Successful in 1m1s
C++ / build (pull_request) Successful in 1m53s
Rust / fmt (pull_request) Successful in 1m13s
Rust / build (pull_request) Successful in 1m48s
Python / buildcheck (pull_request) Successful in 2m43s
Rust / clippy (pull_request) Successful in 2m9s
C++ / clang-tidy (pull_request) Successful in 3m48s
2026-07-10 11:58:35 +02:00
zach d1e3897d02 fix: logo colors 2026-07-10 11:44:01 +02:00
zach 46e24f8543 add initial logo to about page + assets and readme 2026-07-10 11:32:09 +02:00
AramJonghu 1ff7c36723 Merge branch 'main' into 135-issue-pr-templates
C++ / fmt (pull_request) Successful in 11s
JS/TS / fmt (pull_request) Successful in 17s
JS/TS / lint (pull_request) Successful in 17s
Python / fmt (pull_request) Successful in 30s
Python / lint (pull_request) Successful in 32s
Python / test (pull_request) Successful in 57s
Python / typecheck (pull_request) Failing after 52s
C++ / build (pull_request) Successful in 3m4s
Rust / fmt (pull_request) Successful in 1m1s
Rust / build (pull_request) Successful in 1m49s
Python / buildcheck (pull_request) Successful in 2m34s
Rust / clippy (pull_request) Successful in 1m41s
C++ / clang-tidy (pull_request) Successful in 4m41s
2026-07-10 01:32:39 +02:00
AramJonghu f75fef3f55 chore(template): checklist adjustment
C++ / fmt (pull_request) Successful in 8s
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 22s
Python / lint (pull_request) Successful in 32s
Python / fmt (pull_request) Successful in 35s
Python / test (pull_request) Successful in 1m4s
Python / typecheck (pull_request) Failing after 1m3s
C++ / build (pull_request) Successful in 1m55s
Rust / build (pull_request) Successful in 1m54s
Rust / fmt (pull_request) Successful in 1m16s
Python / buildcheck (pull_request) Successful in 2m46s
Rust / clippy (pull_request) Successful in 2m40s
C++ / clang-tidy (pull_request) Successful in 5m36s
2026-07-10 01:16:21 +02:00
AramJonghu 246ee67fb3 update(typecheck): added typecheck in workflow and pyproject
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 17s
Python / fmt (pull_request) Successful in 34s
Python / lint (pull_request) Successful in 31s
Python / test (pull_request) Successful in 59s
Python / typecheck (pull_request) Failing after 53s
C++ / build (pull_request) Successful in 1m56s
Rust / fmt (pull_request) Successful in 1m18s
Rust / build (pull_request) Successful in 1m50s
Rust / clippy (pull_request) Successful in 2m7s
Python / buildcheck (pull_request) Successful in 2m42s
C++ / clang-tidy (pull_request) Successful in 3m49s
2026-07-10 01:09:08 +02:00
AramJonghu 5b5f38a48d feat(templates): Added template yaml files 2026-07-10 01:09:01 +02:00
zach 1266166676 fix: text input field bounds 2026-07-09 14:20:06 +02:00
zach 0fc1a123fa mute cmake install output 2026-07-08 23:08:42 +02:00
zach 672cb07547 feat: import M3Shapes, M3 loading indicator and weather + resources + media revamp in lockscreen 2026-07-08 22:53:19 +02:00
AramJonghu 8d4b910e23 Merge branch 'main' into 135-issue-pr-templates
C++ / fmt (pull_request) Successful in 9s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 20s
Python / fmt (pull_request) Successful in 31s
Python / lint (pull_request) Successful in 29s
Python / test (pull_request) Successful in 1m0s
C++ / build (pull_request) Successful in 3m25s
Rust / fmt (pull_request) Successful in 1m12s
Python / buildcheck (pull_request) Successful in 2m51s
Rust / build (pull_request) Successful in 2m14s
Rust / clippy (pull_request) Successful in 1m52s
C++ / clang-tidy (pull_request) Successful in 6m7s
2026-07-08 22:14:09 +02:00
zach e3b2d33a11 fix: fallback to python wheel if Nuitka is not available 2026-07-08 18:32:21 +02:00
zach 2a40696292 Merge pull request 'chore(ci-image): fix tld in ci-image workflow + additional workflow improvements' (#137) from update-cibuild-tld into main
Reviewed-on: #137
Reviewed-by: zach <zach@brohn.se>
2026-07-08 18:25:10 +02:00
zach 80ee714e91 Merge branch 'main' into update-cibuild-tld
C++ / fmt (pull_request) Successful in 4s
Python / fmt (pull_request) Successful in 58s
JS/TS / lint (pull_request) Successful in 1m14s
JS/TS / fmt (pull_request) Failing after 1m32s
Python / lint (pull_request) Failing after 1m55s
C++ / clang-tidy (pull_request) Successful in 2m55s
C++ / build (pull_request) Successful in 2m58s
Rust / fmt (pull_request) Successful in 1m21s
Python / test (pull_request) Successful in 2m25s
Rust / clippy (pull_request) Successful in 1m31s
Rust / build (pull_request) Successful in 3m5s
Python / buildcheck (pull_request) Successful in 3m25s
2026-07-08 17:50:24 +02:00
zach 2c572c3250 feat: animations in settings search results 2026-07-08 17:49:26 +02:00
AramJonghu 0912a8e40c hotfix(): Forgot to change ruff package as dep
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 15s
Python / fmt (pull_request) Successful in 34s
Python / lint (pull_request) Successful in 33s
Python / test (pull_request) Successful in 59s
C++ / build (pull_request) Successful in 1m40s
Rust / fmt (pull_request) Successful in 1m12s
Rust / build (pull_request) Successful in 1m58s
Python / buildcheck (pull_request) Successful in 2m44s
Rust / clippy (pull_request) Successful in 1m57s
C++ / clang-tidy (pull_request) Successful in 3m37s
2026-07-08 17:30:46 +02:00
AramJonghu 0d17621180 chore(py formatter): Revert from autopep8 -> ruff after config update
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 9s
JS/TS / lint (pull_request) Successful in 20s
Python / fmt (pull_request) Failing after 26s
Python / lint (pull_request) Successful in 29s
Python / test (pull_request) Successful in 1m3s
Rust / fmt (pull_request) Successful in 1m11s
C++ / build (pull_request) Successful in 1m53s
Rust / build (pull_request) Successful in 1m56s
Rust / clippy (pull_request) Successful in 1m45s
Python / buildcheck (pull_request) Successful in 2m44s
C++ / clang-tidy (pull_request) Successful in 3m49s
2026-07-08 17:28:25 +02:00
zach 0ae6d6fc55 chore: format test files
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 19s
Python / lint (pull_request) Successful in 32s
Python / fmt (pull_request) Failing after 37s
Python / test (pull_request) Successful in 54s
C++ / build (pull_request) Successful in 1m57s
Rust / fmt (pull_request) Successful in 1m16s
Rust / build (pull_request) Successful in 1m56s
Python / buildcheck (pull_request) Successful in 2m44s
Rust / clippy (pull_request) Successful in 1m56s
C++ / clang-tidy (pull_request) Successful in 3m46s
2026-07-08 17:01:25 +02:00
zach 9300da258e chore: python code formatted with ruff, ruff formatter + linter, pyproject.toml now in root
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 18s
Python / lint (pull_request) Failing after 32s
Python / fmt (pull_request) Failing after 37s
Python / test (pull_request) Successful in 52s
C++ / build (pull_request) Successful in 1m56s
Rust / fmt (pull_request) Successful in 1m22s
Rust / build (pull_request) Successful in 2m5s
Python / buildcheck (pull_request) Successful in 2m39s
Rust / clippy (pull_request) Successful in 2m1s
C++ / clang-tidy (pull_request) Successful in 3m46s
2026-07-08 16:54:41 +02:00
zach 298cbbf424 Merge branch 'main' into update-cibuild-tld
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 15s
Python / fmt (pull_request) Failing after 30s
Python / lint (pull_request) Successful in 33s
Python / test (pull_request) Successful in 54s
C++ / build (pull_request) Successful in 1m47s
Rust / fmt (pull_request) Successful in 1m16s
Rust / build (pull_request) Successful in 2m0s
Python / buildcheck (pull_request) Successful in 2m41s
Rust / clippy (pull_request) Successful in 1m54s
C++ / clang-tidy (pull_request) Successful in 3m41s
2026-07-08 16:18:15 +02:00
zach b19b630a77 better ddcutil handling, revert to using onMoved brightness slider, fix osd region 2026-07-08 16:17:37 +02:00
AramJonghu 75f0f2071d fix(ci): include zshell python package for buildcheck
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 18s
Python / fmt (pull_request) Failing after 32s
Python / lint (pull_request) Successful in 32s
Python / test (pull_request) Successful in 52s
Rust / fmt (pull_request) Successful in 1m11s
C++ / build (pull_request) Successful in 1m57s
Rust / build (pull_request) Successful in 1m49s
Python / buildcheck (pull_request) Successful in 2m39s
Rust / clippy (pull_request) Successful in 1m45s
C++ / clang-tidy (pull_request) Successful in 3m43s
2026-07-08 14:52:42 +02:00
AramJonghu bfea718547 fix(ci): clang-format pass echo, nuitka full package compile
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 15s
Python / fmt (pull_request) Failing after 34s
Python / lint (pull_request) Successful in 33s
Python / test (pull_request) Successful in 51s
C++ / build (pull_request) Successful in 1m37s
Rust / fmt (pull_request) Successful in 1m8s
Rust / build (pull_request) Successful in 1m52s
Python / buildcheck (pull_request) Successful in 2m37s
Rust / clippy (pull_request) Successful in 1m55s
C++ / clang-tidy (pull_request) Successful in 3m37s
2026-07-08 14:49:02 +02:00
AramJonghu 5505ac19ba refactor(ci): add python workflow, split cpp jobs, add clang-format
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 18s
JS/TS / lint (pull_request) Successful in 17s
Python / fmt (pull_request) Failing after 29s
Python / lint (pull_request) Successful in 35s
Python / test (pull_request) Successful in 56s
C++ / build (pull_request) Successful in 1m49s
Rust / fmt (pull_request) Successful in 1m9s
Rust / build (pull_request) Successful in 1m51s
Python / buildcheck (pull_request) Successful in 2m31s
Rust / clippy (pull_request) Successful in 1m47s
C++ / clang-tidy (pull_request) Successful in 3m29s
2026-07-08 14:37:35 +02:00
AramJonghu 9d2dc281ec refactor(ci): restructure workflows to multi-job per language
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 14s
Rust / fmt (pull_request) Successful in 1m30s
Rust / build (pull_request) Successful in 1m53s
Rust / clippy (pull_request) Successful in 2m20s
C++ / build (pull_request) Successful in 2m54s
2026-07-08 14:28:51 +02:00
AramJonghu 05c8851143 Merge branch 'main' into update-cibuild-tld
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 22s
Python / lint-format (pull_request) Successful in 27s
Python / test (pull_request) Successful in 50s
C++ / build (pull_request) Successful in 2m31s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m34s
2026-07-08 13:51:16 +02:00
zach 1cbe9a9f8a Merge pull request 'Add ahead-of-time compilation for cli and optimize thumbnail caching' (#136) from feat/aot-compilation-cli into main
Reviewed-on: #136
Reviewed-by: AramJonghu <aramjonghu@tutamail.com>
2026-07-08 13:41:18 +02:00
AramJonghu 71b25bff49 chore(ci-image): fix tld in ci-image workflow
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 45s
Python / lint-format (pull_request) Successful in 52s
Python / test (pull_request) Successful in 44s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m50s
C++ / build (pull_request) Successful in 3m40s
2026-07-08 13:21:19 +02:00
zach 87433334c7 fix cmake compilation of python code
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 13s
Python / lint-format (pull_request) Successful in 31s
Python / test (pull_request) Successful in 41s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m41s
C++ / build (pull_request) Successful in 2m27s
2026-07-08 13:01:53 +02:00
zach 6d5609fe5b Add ahead-of-time compilation for cli and optimize thumbnail caching
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 46s
Python / lint-format (pull_request) Successful in 49s
Python / test (pull_request) Successful in 47s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m42s
C++ / build (pull_request) Successful in 3m7s
2026-07-08 12:23:45 +02:00
zach ffefd3e202 clip settings at bar bounds 2026-07-07 18:47:48 +02:00
zach 2db6a57c0b fix: shift background in accordance with content 2026-07-06 19:40:57 +02:00
zach 0c5871e108 add burn-in prevention for lock screen 2026-07-06 14:12:07 +02:00
zach 6ad9fe5e07 settings highlight optimized 2026-07-05 18:01:52 +02:00
zach 8c11aead18 fix: osd stays open when hovered 2026-07-04 15:54:44 +02:00
AramJonghu 5e78b3b492 init(new branch): New branch
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 13s
Python / lint-format (pull_request) Successful in 23s
Python / test (pull_request) Successful in 1m3s
Lint & Format (Rust) / lint-format (pull_request) Successful in 2m36s
C++ / build (pull_request) Successful in 6m21s
2026-07-04 04:54:28 +02:00
zach d013be0f9a fix: include spacing for expand icon tray menu 2026-07-03 17:40:45 +02:00
zach 69774e7759 feat: greeter support hyprland lua 2026-07-03 15:52:27 +02:00
zach cdf66bff23 fix: better width + height calculations for tray menu popouts 2026-07-03 15:02:00 +02:00
zach 562770595f fix: add generic gpu vram support 2026-07-03 12:28:54 +02:00
zach 9126b04b10 fix: close tray menus when hovering bar + showOnHover enabled 2026-07-02 18:50:14 +02:00
zach 55dab8f7ce HyprlandFocusGrab on traymenu stackdepth > 1 2026-07-02 16:15:18 +02:00
zach c62695bfff chore: cleanup more unused files/imports, use new buttonrow for polkit 2026-07-02 13:35:17 +02:00
zach 2b06a33508 chore: cleanup unused files/imports 2026-07-02 12:49:47 +02:00
zach 4d731c5a65 feat: add option for recoloring tray icons + show popout on hover 2026-07-02 11:33:43 +02:00
zach 53836aec1a fix: anim property for record tool 2026-07-01 22:35:58 +02:00
zach 355106cb2b add radius anim to search results 2026-06-30 22:40:08 +02:00
zach 865b5bda53 chore: cleanup comments 2026-06-30 22:27:37 +02:00
zach 2b89c8e4a1 implement search bar functionality in settings 2026-06-30 22:20:48 +02:00
zach 61019204d8 formatter 2026-06-30 15:35:25 +02:00
AramJonghu 951c31ab3d Merge remote-tracking branch 'origin/feat/settings-revamp' 2026-06-30 15:29:27 +02:00
zach 60831de7c5 Merge pull request 'tidy, format, and resolving tidy warnings' (#132) from tidy-warning-fixes into main
Reviewed-on: #132
2026-06-30 14:46:39 +02:00
zach 38b9362515 remove old Settings, rename new
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 18s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m39s
C++ / build (pull_request) Successful in 2m26s
2026-06-30 13:43:34 +02:00
zach deaeac4dbd section headers for screenshot page + rename
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 13s
Python / lint-format (pull_request) Successful in 17s
Python / test (pull_request) Successful in 45s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m39s
C++ / build (pull_request) Successful in 2m23s
2026-06-30 13:31:23 +02:00
zach 157bdd8fd9 new spin box, textfield and searchbar
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 30s
Python / test (pull_request) Successful in 43s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m38s
C++ / build (pull_request) Successful in 2m18s
2026-06-30 13:25:12 +02:00
AramJonghu 45350210cc fix&revert(qalculator): unassigned this to calculator pointer fixed, revert of succesful test
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 20s
Python / lint-format (pull_request) Successful in 41s
Python / test (pull_request) Successful in 1m51s
Lint & Format (Rust) / lint-format (pull_request) Successful in 2m0s
C++ / build (pull_request) Successful in 3m41s
2026-06-30 04:49:55 +02:00
AramJonghu 85944ec966 force harmless lint warning to check ci/cd
Python / lint-format (pull_request) Successful in 26s
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 30s
Python / test (pull_request) Successful in 50s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m43s
C++ / build (pull_request) Successful in 2m25s
2026-06-30 04:42:39 +02:00
AramJonghu 3c9df82594 CI/CD: attempt only user tidy warnings
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 16s
Python / lint-format (pull_request) Successful in 29s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m39s
C++ / build (pull_request) Successful in 2m35s
2026-06-30 04:36:22 +02:00
AramJonghu 1cdcecae68 CI/CD: revert
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 25s
Python / lint-format (pull_request) Successful in 29s
Python / test (pull_request) Successful in 41s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m39s
C++ / build (pull_request) Successful in 2m28s
2026-06-30 04:27:44 +02:00
AramJonghu d2368c8c10 CI/CD: testing warnings as errors for CI/CD only
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 20s
Python / lint-format (pull_request) Successful in 49s
Python / test (pull_request) Successful in 1m11s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m32s
C++ / build (pull_request) Failing after 2m26s
2026-06-30 04:17:43 +02:00
AramJonghu b8f79c51ae CI/CD: updated, researched other CI/CD implementations
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 16s
Python / lint-format (pull_request) Successful in 31s
Python / test (pull_request) Successful in 44s
C++ / build (pull_request) Successful in 2m18s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m47s
2026-06-30 04:02:22 +02:00
AramJonghu 25e1610e2b CI/CD: updated, should not stop the check now due to diagnostic demotion
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 14s
Python / test (pull_request) Successful in 48s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m46s
C++ / build (pull_request) Successful in 2m26s
2026-06-30 03:54:47 +02:00
AramJonghu 49a65becff CI/CD: updated cpp to reduce false flags, focus on dev tidy check
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 30s
Python / test (pull_request) Successful in 42s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m37s
C++ / build (pull_request) Successful in 2m23s
2026-06-30 03:44:35 +02:00
AramJonghu 87c9f85ac7 fix(hyprextras): false flag recursion
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 13s
Python / lint-format (pull_request) Successful in 21s
Python / test (pull_request) Successful in 47s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m53s
C++ / build (pull_request) Successful in 2m22s
2026-06-30 03:38:39 +02:00
AramJonghu 532e5a0a03 clang-tidy: reordering 2026-06-30 03:38:16 +02:00
AramJonghu dcc535d213 unused nolint
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 15s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m46s
C++ / build (pull_request) Successful in 2m26s
2026-06-30 03:27:01 +02:00
AramJonghu e347671edd missing commas clang-tidy 2026-06-30 03:23:36 +02:00
AramJonghu d4e4152bdc leftover format file
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 19s
Python / lint-format (pull_request) Successful in 25s
Python / test (pull_request) Successful in 46s
C++ / build (pull_request) Successful in 3m19s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m9s
2026-06-30 03:18:42 +02:00
AramJonghu 728bdc85bc fix(clang-tidy/analyzer): resolving false positives
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 9s
Python / lint-format (pull_request) Successful in 26s
Python / test (pull_request) Successful in 47s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m54s
C++ / build (pull_request) Successful in 3m25s
2026-06-30 03:17:52 +02:00
AramJonghu 944694966b tidy(blobmaterial&circularindicatormanager): warning fixes, readability and modernize headers.
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 9s
Python / lint-format (pull_request) Successful in 17s
Python / test (pull_request) Successful in 48s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m41s
C++ / build (pull_request) Successful in 2m29s
2026-06-30 03:08:32 +02:00
AramJonghu 1e31e14de8 format(remainder): clang-format remainder of files
Python / lint-format (pull_request) Successful in 27s
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 48s
Python / test (pull_request) Successful in 1m2s
C++ / build (pull_request) Successful in 2m15s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m25s
2026-06-30 02:10:37 +02:00
AramJonghu 658be09da2 fix(buttonrow): restore private specifier removed by clang-format 2026-06-30 02:10:17 +02:00
AramJonghu 467e44bb9f tidy&format(all): all files formatted and relevant warnings resolved
C++ / build (pull_request) Failing after 15s
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 28s
Python / lint-format (pull_request) Successful in 45s
Python / test (pull_request) Successful in 38s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m45s
2026-06-30 02:04:24 +02:00
AramJonghu fed9372b35 refactor(tickingservice): flatten nested if blocks with early returns 2026-06-30 01:54:22 +02:00
AramJonghu b2cddea636 fix(gpu): use epsilon comparison instead of == for floating-point guards 2026-06-30 01:36:40 +02:00
AramJonghu 396825d785 fix(desktopmodel): cast qsizetype to int to suppress -Wshorten-64-to-32 2026-06-30 01:36:14 +02:00
AramJonghu f439456ff4 fix(strokecanvasrenderer): use qreal instead of float in drawHoverCursor
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 27s
Python / lint-format (pull_request) Successful in 31s
Python / test (pull_request) Successful in 1m0s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m39s
C++ / build (pull_request) Successful in 2m17s
2026-06-30 01:26:19 +02:00
AramJonghu 4a18edfc78 fix(strokecanvasitem): use qreal instead of float to suppress -Wdouble-promotion
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 16s
Python / lint-format (pull_request) Successful in 23s
Python / test (pull_request) Successful in 48s
C++ / build (pull_request) Successful in 2m20s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m59s
2026-06-30 01:22:40 +02:00
AramJonghu 3eecbc16bc perf(lazylistview): collect pending indices and hoist layoutSize cast in updatePolishdbus workaround for session 2026-06-30 00:23:23 +02:00
zach 437f935f73 add about page in settings
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 13s
Python / test (pull_request) Successful in 53s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m35s
C++ / build (pull_request) Successful in 2m32s
2026-06-29 23:54:54 +02:00
AramJonghu b939224e9d action secret added so we have push permissions for docker
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 25s
Python / lint-format (pull_request) Successful in 28s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m53s
C++ / build (pull_request) Successful in 2m31s
2026-06-29 23:01:54 +02:00
AramJonghu 644a1e0c78 workflow update; node and docker deps added
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 20s
Python / test (pull_request) Successful in 52s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m40s
C++ / build (pull_request) Successful in 2m43s
2026-06-29 22:40:28 +02:00
zach 3f7bbc01aa Merge branch 'main' into feat/settings-revamp
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 18s
Python / lint-format (pull_request) Successful in 18s
Python / test (pull_request) Successful in 1m13s
Lint & Format (Rust) / lint-format (pull_request) Successful in 2m21s
C++ / build (pull_request) Successful in 4m35s
2026-06-29 22:10:39 +02:00
AramJonghuandzach bc9d8af0fe update to clang-tidy + workflow improvement cpp build & lint check (#130)
### Goal

Idea is to reduce the annoyances and research which clang-tidy rules make sense and actually have benefits in our project.

Also considering immediately resolving most if not all tidy warnings.

### Current Changes

- `.clang-tidy` has changes to follow the guidelines we have been following silently. Some rules were different from how we program.
    - Note that naming is completely removed and won't be checked. In a future PR (where we go over the code to fix linting issues), we can reintroduce them and make sure they fit our codebase consistently.
- tidy rules are not considered errors anymore (stopped compile).
- CI/CD addition to build check and clang-tidy check. Tried to get clang-tidy check to show when failed, but that causes complications in its checks; so now it is simply silent when failing.
- Dockerfile that creates an arch container as cache for the CI/CD, prevents redownload of dependencies each run. Instead, it runs weekly (or optionally a different interval).

### Current complications

- To push the docker container build, it would require this webserver to allow larger filesize pushes (need ~2GB). Current workaround is arguably better where docker build is pushed to runner server.
- Figuring out which clang-tidy rules make sense.

Reviewed-on: #130
Co-authored-by: AramJonghu <aramjonghu@tutamail.com>
Co-committed-by: AramJonghu <aramjonghu@tutamail.com>
2026-06-29 22:10:26 +02:00
zach 01d521b42d Merge branch 'main' into feat/settings-revamp
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 17s
Python / test (pull_request) Successful in 30s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m7s
2026-06-29 19:37:24 +02:00
zach 7d65578a5f proper VERSION var 2026-06-29 19:37:11 +02:00
zach 77ec1c87f8 Merge branch 'main' into feat/settings-revamp
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 29s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m8s
2026-06-29 18:59:24 +02:00
zach f883b3d7fe versioning 2026-06-29 18:57:32 +02:00
zach e685500698 revert certain changes for blobs
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 19s
Python / test (pull_request) Successful in 30s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m14s
2026-06-28 22:49:15 +02:00
zach 04481ae7e1 sidebar menu on top
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 28s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m8s
2026-06-27 00:11:18 +02:00
zach 82a660229b remove network-dev folder
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 17s
Python / test (pull_request) Successful in 28s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m7s
2026-06-26 17:25:25 +02:00
zach ce6e314fde chore: regions now manually set, moved to separate file
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 17s
Python / test (pull_request) Successful in 31s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m8s
2026-06-26 17:23:56 +02:00
zach 0b92cbb3b4 add corner fill
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 9s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 27s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m8s
2026-06-25 18:58:21 +02:00
zach 6a15be7b15 sys tray spacing
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 29s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m17s
2026-06-25 12:57:11 +02:00
zach 01c63ebead blobpopup positioning and radius changes
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 19s
Python / test (pull_request) Successful in 29s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m43s
2026-06-24 23:06:29 +02:00
zach ecfa1115cd wonky fix for cropping rect desync
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 14s
Python / lint-format (pull_request) Successful in 18s
Python / test (pull_request) Successful in 28s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m11s
2026-06-24 20:21:36 +02:00
zach d08b2b7ac6 correct index for subpages
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 20s
Python / test (pull_request) Successful in 28s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m7s
2026-06-24 15:42:50 +02:00
zach 4df31d7564 added services page + rename barConfig json property to bar, migration helper function
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 29s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m6s
2026-06-24 15:30:33 +02:00
zach 5c6882d2a8 added panels page
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 9s
Python / lint-format (pull_request) Successful in 28s
Python / test (pull_request) Successful in 28s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m6s
2026-06-23 23:06:30 +02:00
zach 6a80961b2b added audio and apps page in settings
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 18s
Python / test (pull_request) Successful in 28s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m6s
2026-06-23 22:32:56 +02:00
zach 2366901b24 Merge branch 'main' into feat/settings-revamp
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 18s
Python / lint-format (pull_request) Successful in 29s
Python / test (pull_request) Successful in 55s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m24s
2026-06-23 16:24:01 +02:00
zach ea4d5376f6 initial commit for settings revamp
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 15s
Python / lint-format (pull_request) Successful in 29s
Python / test (pull_request) Successful in 54s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m34s
2026-06-23 16:22:56 +02:00
589 changed files with 23348 additions and 26934 deletions
+3 -3
View File
@@ -1,15 +1,15 @@
--- ---
BasedOnStyle: LLVM BasedOnStyle: LLVM
AccessModifierOffset: 0 AccessModifierOffset: 0
AlignAfterOpenBracket: Align AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false AlignConsecutiveDeclarations: false
AlignOperands: Align AlignOperands: Align
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortFunctionsOnASingleLine: Inline AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never AllowShortIfStatementsOnASingleLine: WithoutElse
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: false BinPackArguments: false
BinPackParameters: false BinPackParameters: false
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
+15 -19
View File
@@ -2,29 +2,25 @@
Checks: > Checks: >
-*, -*,
bugprone-*, bugprone-*,
-bugprone-throwing-static-initialization,
-bugprone-invalid-enum-default-initialization,
-bugprone-suspicious-include,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-narrowing-conversions,
-bugprone-implicit-widening-of-multiplication-result,
clang-analyzer-*, clang-analyzer-*,
modernize-*, cppcoreguidelines-init-variables,
-modernize-use-trailing-return-type, misc-no-recursion,
performance-*, concurrency-mt-unsafe,
readability-braces-around-statements,
readability-else-after-return, readability-else-after-return,
readability-identifier-naming, readability-make-member-function-const,
readability-redundant-*, readability-redundant-*,
-readability-redundant-inline-specifier,
readability-simplify-*, readability-simplify-*,
CheckOptions: modernize-use-override,
readability-identifier-naming.ClassCase: CamelCase modernize-use-nullptr,
readability-identifier-naming.EnumCase: CamelCase modernize-deprecated-headers,
readability-identifier-naming.FunctionCase: camelBack
readability-identifier-naming.MemberCase: camelBack
readability-identifier-naming.MemberPrefix: m_
readability-identifier-naming.MethodCase: camelBack
readability-identifier-naming.NamespaceCase: CamelCase
readability-identifier-naming.ParameterCase: camelBack
readability-identifier-naming.PrivateMemberPrefix: m_
readability-identifier-naming.StaticConstantCase: UPPER_CASE
readability-identifier-naming.StaticConstantPrefix: k
readability-identifier-naming.VariableCase: camelBack
WarningsAsErrors: "*"
HeaderFilterRegex: ".*" HeaderFilterRegex: ".*"
FormatStyle: file FormatStyle: file
+108
View File
@@ -0,0 +1,108 @@
name: Bug Report
about: Something broke
title: "bug: "
labels:
- bug
body:
- type: textarea
id: description
attributes:
label: What happened
placeholder: Describe the bug
validations:
required: true
- type: textarea
id: expected
attributes:
label: What should happen
placeholder: Expected behavior
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1.
2.
3.
render: shell
validations:
required: true
- type: dropdown
id: os
attributes:
label: OS
options:
- NixOS
- Arch
- Debian / Ubuntu
- Fedora
- Alpine
- Artix
- Gentoo
- Other
validations:
required: false
- type: input
id: other-os
attributes:
label: Other OS (if "Other" above)
placeholder: e.g. Void, Gentoo, FreeBSD
validations:
required: false
- type: dropdown
id: init
attributes:
label: Init system
description: Relevant for UWSM configuration
options:
- systemd
- non-systemd (openrc / runit / s6 / ...)
validations:
required: false
- type: input
id: other-init
attributes:
label: Other init system (if "non-systemd" above)
placeholder: e.g. openrc, runit, s6, dinit
validations:
required: false
- type: input
id: qt-version
attributes:
label: Qt version
placeholder: 6.11.1
validations:
required: false
- type: input
id: commit
attributes:
label: Branch / commit
placeholder: main / abc1234
validations:
required: false
- type: textarea
id: logs
attributes:
label: Logs / backtrace / screenshots
render: shell
validations:
required: false
- type: textarea
id: workaround
attributes:
label: Found a workaround?
validations:
required: false
+51
View File
@@ -0,0 +1,51 @@
name: Feature Request
about: Idea or improvement
title: "feat: "
labels:
- enhancement
body:
- type: textarea
id: problem
attributes:
label: What's missing / annoying
placeholder: The use case or pain point
validations:
required: true
- type: textarea
id: solution
attributes:
label: How should it work
placeholder: Describe the desired behavior
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Other approaches considered
validations:
required: false
- type: dropdown
id: scope
attributes:
label: Area
options:
- Core / Daemon
- UI / Components
- Plugin system
- CMake / Build
- CI / Tooling
- Documentation
- Other
validations:
required: false
- type: textarea
id: context
attributes:
label: Mockups / references / notes
validations:
required: false
+59
View File
@@ -0,0 +1,59 @@
name: Pull Request
about: Submit changes
title: ""
labels: []
body:
- type: textarea
id: description
attributes:
label: What & why
placeholder: Describe the change and motivation
validations:
required: true
- type: input
id: issue
attributes:
label: Related issue
placeholder: "#123"
validations:
required: false
- type: dropdown
id: type
attributes:
label: Type
options:
- Bug fix
- New feature
- Refactor / style
- CI / build / tooling
- Documentation
validations:
required: true
- type: checkboxes
id: tested
attributes:
label: Tested
options:
- label: Build succeeds
- label: Existing tests pass
- label: Manually verified
- type: textarea
id: breaking
attributes:
label: Breaking changes?
placeholder: API/ABI breakage? Migration path?
- type: checkboxes
id: checklist
attributes:
label: Checklist
options:
- label: CI passes (format, lint, typecheck)
- label: Clean commits
- label: No new warnings
- label: Docs updated if needed
+30
View File
@@ -0,0 +1,30 @@
name: Rebuild CI Image
on:
schedule:
- cron: "0 6 * * 1"
workflow_dispatch:
jobs:
build:
runs-on: alpine
container:
image: node:26-alpine
env:
IMAGE: git.aramjonghu.dev/aramjonghu/zshell-ci:latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Docker CLI
run: apk add --no-cache docker-cli
- name: Login to registry
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.aramjonghu.dev --username aramjonghu --password-stdin
- name: Build image
run: docker build -t "$IMAGE" -f ci/Dockerfile .
- name: Push image
run: docker push "$IMAGE"
+62
View File
@@ -0,0 +1,62 @@
name: C++
on:
pull_request:
jobs:
fmt:
runs-on: alpine
container:
image: git.aramjonghu.dev/aramjonghu/zshell-ci:latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Format check
run: |
find . \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) \
-not -path './build/*' \
-exec clang-format -i --style=file {} +
git diff --exit-code && echo "clang-format: passed"
build:
runs-on: alpine
container:
image: git.aramjonghu.dev/aramjonghu/zshell-ci:latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure
run: cmake -B build -G Ninja -DENABLE_MODULES=plugin -DCMAKE_BUILD_TYPE=Release
- name: Build
run: ninja -C build
clang-tidy:
runs-on: alpine
container:
image: git.aramjonghu.dev/aramjonghu/zshell-ci:latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure
run: cmake -B build -G Ninja -DENABLE_MODULES=plugin -DCMAKE_BUILD_TYPE=Release
- name: Build
run: ninja -C build
- name: clang-tidy
run: |
sed -i 's/-mno-direct-extern-access //g' build/compile_commands.json
set -o pipefail
run-clang-tidy -p build -j $(nproc) -header-filter="Plugins/.*" 2>&1 | \
grep -v 'Suppressed\|non-user\|non-system\|unknown argument.*mno-direct\|Found compiler error\|warnings generated\.\|^Use -header-filter'
@@ -1,10 +1,10 @@
name: Lint & Format (JS/TS) name: JS/TS
on: on:
pull_request: pull_request:
jobs: jobs:
lint-format: fmt:
runs-on: alpine runs-on: alpine
container: node:26-alpine container: node:26-alpine
@@ -18,7 +18,6 @@ jobs:
git git
- name: Prettier - name: Prettier
continue-on-error: true
run: | run: |
if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then
npx --yes prettier --check "**/*.{js,jsx,ts,tsx,mjs,cjs}" --ignore-path .prettierignore npx --yes prettier --check "**/*.{js,jsx,ts,tsx,mjs,cjs}" --ignore-path .prettierignore
@@ -26,6 +25,19 @@ jobs:
echo "No JS/TS files found" echo "No JS/TS files found"
fi fi
lint:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git
- name: ESLint - name: ESLint
run: | run: |
if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then
-65
View File
@@ -1,65 +0,0 @@
name: Python
on:
pull_request:
jobs:
lint-format:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git \
python3 \
py3-pip
python3 -m venv .venv
. .venv/bin/activate
pip install --no-cache-dir ruff
- name: Format check
continue-on-error: true
run: |
. .venv/bin/activate
ruff format --check .
- name: Lint
run: |
. .venv/bin/activate
ruff check .
test:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git \
python3 \
py3-pip \
py3-pillow \
build-base
python3 -m venv .venv
. .venv/bin/activate
pip install --no-cache-dir \
typer \
pillow \
materialyoucolor \
jinja2 \
pytest
- name: Test
run: |
. .venv/bin/activate
cd cli
python -m pytest tests/ -v
-85
View File
@@ -1,85 +0,0 @@
name: Lint & Format (Rust)
on:
pull_request:
jobs:
lint-format:
runs-on: alpine
container: node:26-alpine
env:
CARGO_HOME: ${{ github.workspace }}/.cargo
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache cargo packages
uses: actions/cache@v4
env:
cache-name: cache-cargo-packages
with:
path: |
.cargo/registry
.cargo/git
target
key: rust-${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
rust-${{ runner.os }}-build-${{ env.cache-name }}-
rust-${{ runner.os }}-build-
rust-
- name: Install tools
run: |
apk add --no-cache \
git \
cargo \
rust \
rustfmt \
rust-clippy
- id: format-check
name: Format check
continue-on-error: true
run: |
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
status=0
for manifest in $(find . -name "Cargo.toml"); do
cargo fmt --manifest-path "$manifest" --check && \
echo "$manifest: formatting OK" || \
{ echo "$manifest: needs formatting"; status=1; }
done
exit $status
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
echo "Rust files found but no Cargo.toml"
exit 1
else
echo "No Rust project found"
fi
- id: clippy
name: Clippy
run: |
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
status=0
for manifest in $(find . -name "Cargo.toml"); do
cargo clippy --manifest-path "$manifest" --all-targets --all-features -- -D warnings && \
echo "$manifest: Clippy passed" || \
{ echo "$manifest: Clippy failed"; status=1; }
done
exit $status
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
echo "Rust files found but no Cargo.toml"
exit 1
else
echo "No Rust project found"
fi
- name: Check results
if: always()
run: |
if [ "${{ steps.format-check.outcome }}" = "failure" ] || [ "${{ steps.clippy.outcome }}" = "failure" ]; then
echo "One or more checks failed"
exit 1
fi
echo "All checks passed"
+132
View File
@@ -0,0 +1,132 @@
name: Python
on:
pull_request:
jobs:
fmt:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git \
python3 \
py3-pip
python3 -m venv .venv
. .venv/bin/activate
pip install --no-cache-dir ruff
- name: Format check
run: |
. .venv/bin/activate
ruff format --check .
lint:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git \
python3 \
py3-pip
python3 -m venv .venv
. .venv/bin/activate
pip install --no-cache-dir ruff
- name: Lint
run: |
. .venv/bin/activate
ruff check .
test:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git \
python3 \
py3-pip \
py3-pillow \
build-base
python3 -m venv .venv
. .venv/bin/activate
pip install --no-cache-dir \
typer \
pillow \
materialyoucolor \
jinja2 \
pytest
- name: Test
run: |
. .venv/bin/activate
cd cli
python -m pytest tests/ -v
typecheck:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git \
python3 \
py3-pip
python3 -m venv .venv
. .venv/bin/activate
pip install --no-cache-dir basedpyright typer pillow materialyoucolor jinja2
- name: Type check
run: |
. .venv/bin/activate
basedpyright
buildcheck:
runs-on: alpine
container: node:26-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install tools
run: |
apk add --no-cache \
git \
python3 \
py3-pip \
build-base \
python3-dev \
gcc \
g++
python3 -m venv .venv
. .venv/bin/activate
pip install --no-cache-dir nuitka
- name: Nuitka module check
run: |
. .venv/bin/activate
nuitka --module --include-package=zshell cli/src/zshell/
+152
View File
@@ -0,0 +1,152 @@
name: Rust
on:
pull_request:
jobs:
build:
runs-on: alpine
container: node:26-alpine
env:
CARGO_HOME: ${{ github.workspace }}/.cargo
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache cargo packages
uses: actions/cache@v4
env:
cache-name: cache-cargo-packages
with:
path: |
.cargo/registry
.cargo/git
target
key: rust-build-${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
rust-${{ runner.os }}-build-${{ env.cache-name }}-
rust-${{ runner.os }}-build-
rust-
- name: Install tools
run: |
apk add --no-cache \
git \
cargo \
rust
- name: Cargo check
run: |
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
for manifest in $(find . -name "Cargo.toml"); do
cargo check --manifest-path "$manifest" && \
echo "$manifest: check passed" || \
{ echo "$manifest: check failed"; exit 1; }
done
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
echo "Rust files found but no Cargo.toml"
exit 1
else
echo "No Rust project found"
fi
fmt:
runs-on: alpine
container: node:26-alpine
env:
CARGO_HOME: ${{ github.workspace }}/.cargo
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache cargo packages
uses: actions/cache@v4
env:
cache-name: cache-cargo-packages
with:
path: |
.cargo/registry
.cargo/git
target
key: rust-fmt-${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
rust-${{ runner.os }}-build-${{ env.cache-name }}-
rust-${{ runner.os }}-build-
rust-
- name: Install tools
run: |
apk add --no-cache \
git \
cargo \
rust \
rustfmt
- name: Format check
run: |
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
status=0
for manifest in $(find . -name "Cargo.toml"); do
cargo fmt --manifest-path "$manifest" --check && \
echo "$manifest: formatting OK" || \
{ echo "$manifest: needs formatting"; status=1; }
done
exit $status
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
echo "Rust files found but no Cargo.toml"
exit 1
else
echo "No Rust project found"
fi
clippy:
runs-on: alpine
container: node:26-alpine
env:
CARGO_HOME: ${{ github.workspace }}/.cargo
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache cargo packages
uses: actions/cache@v4
env:
cache-name: cache-cargo-packages
with:
path: |
.cargo/registry
.cargo/git
target
key: rust-clippy-${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
rust-${{ runner.os }}-build-${{ env.cache-name }}-
rust-${{ runner.os }}-build-
rust-
- name: Install tools
run: |
apk add --no-cache \
git \
cargo \
rust \
rust-clippy
- name: Clippy
run: |
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
status=0
for manifest in $(find . -name "Cargo.toml"); do
cargo clippy --manifest-path "$manifest" --all-targets --all-features -- -D warnings && \
echo "$manifest: Clippy passed" || \
{ echo "$manifest: Clippy failed"; status=1; }
done
exit $status
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
echo "Rust files found but no Cargo.toml"
exit 1
else
echo "No Rust project found"
fi
+1
View File
@@ -15,3 +15,4 @@ dist/
**/target/ **/target/
**/test-plugins/ **/test-plugins/
**/Charts/ **/Charts/
network-dev/
+156 -11
View File
@@ -1,37 +1,163 @@
cmake_minimum_required(VERSION 3.19) cmake_minimum_required(VERSION 3.19)
project(ZShell) if(NOT DEFINED VERSION)
execute_process(
COMMAND git describe --tags --abbrev=0
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_LAST_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if (GIT_LAST_TAG)
string(REGEX REPLACE "^v" "" GIT_LAST_TAG "${GIT_LAST_TAG}")
string(REPLACE "." ";" VERSION_LIST "${GIT_LAST_TAG}")
list(GET VERSION_LIST 0 VERSION_MAJOR)
list(GET VERSION_LIST 1 VERSION_MINOR)
execute_process(
COMMAND git rev-list v${VERSION_MAJOR}.${VERSION_MINOR}.0..HEAD --count
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_PATCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
endif()
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
project(ZShell VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
message(STATUS "ZShell version: ${VERSION}")
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(ENABLE_MODULES "plugin;shell" CACHE STRING "Modules to build/install") set(ENABLE_MODULES "plugin;shell;m3shapes" CACHE STRING "Modules to build/install")
set(INSTALL_LIBDIR "usr/lib/ZShell" CACHE STRING "Library install dir") set(INSTALL_LIBDIR "usr/lib/ZShell" CACHE STRING "Library install dir")
set(INSTALL_QMLDIR "usr/lib/qt6/qml" CACHE STRING "QML install dir") set(INSTALL_QMLDIR "usr/lib/qt6/qml" CACHE STRING "QML install dir")
set(INSTALL_QSCONFDIR "etc/xdg/quickshell/zshell" CACHE STRING "Quickshell config install dir") set(INSTALL_QSCONFDIR "etc/xdg/quickshell/zshell" CACHE STRING "Quickshell config install dir")
set(INSTALL_GREETERCONFDIR "etc/xdg/quickshell/zshell-greeter" CACHE STRING "Quickshell greeter install dir") set(INSTALL_GREETERCONFDIR "etc/xdg/quickshell/zshell-greeter" CACHE STRING "Quickshell greeter install dir")
set(CMAKE_INSTALL_MESSAGE NEVER)
add_compile_options( add_compile_options(
-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wall -Wextra -Wpedantic -Wshadow -Wconversion
-Wold-style-cast -Wnull-dereference -Wdouble-promotion -Wold-style-cast -Wnull-dereference -Wdouble-promotion
-Wformat=2 -Wfloat-equal -Woverloaded-virtual -Wformat=2 -Wfloat-equal -Woverloaded-virtual
-Wsign-conversion -Wredundant-decls -Wswitch -Wsign-conversion -Wredundant-decls -Wswitch
-Wunreachable-code -Wunreachable-code
) )
if("shell" IN_LIST ENABLE_MODULES)
# Build settings index
find_package(Python3 COMPONENTS Interpreter REQUIRED)
set(SETTINGS_INDEX_JSON "${CMAKE_BINARY_DIR}/settings-index.json")
execute_process(
COMMAND ${Python3_EXECUTABLE}
"${CMAKE_SOURCE_DIR}/scripts/build-settings-index.py"
"${CMAKE_SOURCE_DIR}/Modules/Settings"
"${SETTINGS_INDEX_JSON}"
RESULT_VARIABLE SETTINGS_INDEX_RESULT
)
if(NOT SETTINGS_INDEX_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to build settings search index")
endif()
# Nuitka compilation
set(ZSHELL_CLI_BUILD_DIR "${CMAKE_BINARY_DIR}/zshell-cli")
set(ZSHELL_CLI_DIST "${ZSHELL_CLI_BUILD_DIR}/zshell.dist")
set(ZSHELL_CLI_SRC "${CMAKE_SOURCE_DIR}/cli/src/zshell")
find_program(NUITKA_EXECUTABLE nuitka)
if(NUITKA_EXECUTABLE)
file(GLOB_RECURSE ZSHELL_CLI_SOURCES CONFIGURE_DEPENDS
"${ZSHELL_CLI_SRC}/*.py"
)
file(GLOB_RECURSE ZSHELL_CLI_ASSETS CONFIGURE_DEPENDS
"${ZSHELL_CLI_SRC}/assets/*"
)
add_custom_command(
OUTPUT "${ZSHELL_CLI_DIST}/zshell-cli"
COMMAND ${CMAKE_COMMAND} -E make_directory "${ZSHELL_CLI_BUILD_DIR}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${ZSHELL_CLI_DIST}"
COMMAND
${NUITKA_EXECUTABLE}
--standalone
--include-data-dir=${CMAKE_SOURCE_DIR}/cli/src/zshell/assets=zshell/assets
--output-dir=${ZSHELL_CLI_BUILD_DIR}
--output-filename=zshell-cli
${CMAKE_SOURCE_DIR}/cli/src/zshell/
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/cli
DEPENDS ${ZSHELL_CLI_SOURCES} ${ZSHELL_CLI_ASSETS}
)
add_custom_target(zshell-cli ALL DEPENDS "${ZSHELL_CLI_DIST}/zshell-cli")
install(PROGRAMS "${ZSHELL_CLI_DIST}/zshell-cli" DESTINATION "${INSTALL_LIBDIR}/zshell-cli")
install(DIRECTORY "${ZSHELL_CLI_DIST}/" DESTINATION "${INSTALL_LIBDIR}/zshell-cli" PATTERN "zshell-cli" EXCLUDE)
configure_file(
"${CMAKE_SOURCE_DIR}/Plugins/cmake/zshell-cli.cmake.in"
"${CMAKE_BINARY_DIR}/Plugins/cmake/zshell-cli.cmake"
@ONLY
)
install(SCRIPT "${CMAKE_BINARY_DIR}/Plugins/cmake/zshell-cli.cmake")
else()
message(STATUS "Nuitka not found, building zshell-cli as a Python wheel instead")
find_package(Python3 COMPONENTS Interpreter REQUIRED)
set(ZSHELL_CLI_DIR "${CMAKE_SOURCE_DIR}")
set(ZSHELL_CLI_DIST_DIR "${ZSHELL_CLI_DIR}/dist")
set(ZSHELL_CLI_WHEEL_STAMP "${CMAKE_BINARY_DIR}/zshell-cli/wheel.stamp")
file(GLOB_RECURSE ZSHELL_CLI_SOURCES CONFIGURE_DEPENDS
"${ZSHELL_CLI_DIR}/src/zshell/*.py"
)
file(GLOB_RECURSE ZSHELL_CLI_ASSETS CONFIGURE_DEPENDS
"${ZSHELL_CLI_DIR}/src/zshell/assets/*"
)
add_custom_command(
OUTPUT "${ZSHELL_CLI_WHEEL_STAMP}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/zshell-cli"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${ZSHELL_CLI_DIST_DIR}"
COMMAND ${Python3_EXECUTABLE} -m build --wheel --no-isolation
COMMAND ${CMAKE_COMMAND} -E touch "${ZSHELL_CLI_WHEEL_STAMP}"
WORKING_DIRECTORY "${ZSHELL_CLI_DIR}"
DEPENDS ${ZSHELL_CLI_SOURCES} ${ZSHELL_CLI_ASSETS}
COMMENT "Building zshell-cli python wheel"
)
add_custom_target(zshell-cli ALL DEPENDS "${ZSHELL_CLI_WHEEL_STAMP}")
configure_file(
"${CMAKE_SOURCE_DIR}/Plugins/cmake/zshell-cli-python.cmake.in"
"${CMAKE_BINARY_DIR}/Plugins/cmake/zshell-cli-python.cmake"
@ONLY
)
install(SCRIPT "${CMAKE_BINARY_DIR}/Plugins/cmake/zshell-cli-python.cmake")
endif()
endif()
if("plugin" IN_LIST ENABLE_MODULES) if("plugin" IN_LIST ENABLE_MODULES)
add_subdirectory(Plugins) add_subdirectory(Plugins)
endif() endif()
if("shell" IN_LIST ENABLE_MODULES) if("shell" IN_LIST ENABLE_MODULES)
foreach(dir assets scripts Components Config Modules Daemons Drawers Effects Helpers Paths) foreach(dir assets scripts Components Services Modules Daemons Drawers Effects Helpers Paths)
install(DIRECTORY ${dir} DESTINATION "${INSTALL_QSCONFDIR}") install(DIRECTORY ${dir} DESTINATION "${INSTALL_QSCONFDIR}")
endforeach() endforeach()
# Disable watching for changes # Disable watching for changes
file(READ shell.qml SHELL_QML) file(READ shell.qml SHELL_QML)
@@ -42,3 +168,22 @@ if("shell" IN_LIST ENABLE_MODULES)
# Greeter # Greeter
install(DIRECTORY Greeter/ DESTINATION "${INSTALL_GREETERCONFDIR}") install(DIRECTORY Greeter/ DESTINATION "${INSTALL_GREETERCONFDIR}")
endif() endif()
if("m3shapes" IN_LIST ENABLE_MODULES)
message(STATUS "Fetching M3Shapes module")
include(FetchContent)
set(M3SHAPES_REV bdc327b29f95394a732baf3c9b19658ba23755b6)
FetchContent_Declare(
m3shapes_external
GIT_REPOSITORY https://github.com/soramanew/m3shapes.git
GIT_TAG ${M3SHAPES_REV}
SOURCE_DIR "${CMAKE_BINARY_DIR}/_deps/m3shapes-${M3SHAPES_REV}"
)
FetchContent_MakeAvailable(m3shapes_external)
message(STATUS "Done fetching M3Shapes module")
# Fix m3shapes wrong rpath
if(TARGET m3shapesplugin)
set_target_properties(m3shapesplugin PROPERTIES INSTALL_RPATH "$ORIGIN")
endif()
endif()
+12 -12
View File
@@ -1,5 +1,5 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
AnchorAnimation { AnchorAnimation {
enum Type { enum Type {
@@ -20,32 +20,32 @@ AnchorAnimation {
duration: { duration: {
if (type < AnchorAnim.StandardSmall || type > AnchorAnim.SlowSpatial) if (type < AnchorAnim.StandardSmall || type > AnchorAnim.SlowSpatial)
return Appearance.anim.durations.expressiveDefaultSpatial; return Tokens.anim.durations.expressiveDefaultSpatial;
if (type == AnchorAnim.FastSpatial) if (type == AnchorAnim.FastSpatial)
return Appearance.anim.durations.expressiveFastSpatial; return Tokens.anim.durations.expressiveFastSpatial;
if (type == AnchorAnim.DefaultSpatial) if (type == AnchorAnim.DefaultSpatial)
return Appearance.anim.durations.expressiveDefaultSpatial; return Tokens.anim.durations.expressiveDefaultSpatial;
if (type == AnchorAnim.SlowSpatial) if (type == AnchorAnim.SlowSpatial)
return Appearance.anim.durations.large; return Tokens.anim.durations.large;
const types = ["small", "normal", "large", "extraLarge"]; const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; const idx = type % 4;
return Appearance.anim.durations[types[idx]]; return Tokens.anim.durations[types[idx]];
} }
easing.bezierCurve: { easing.bezierCurve: {
if (type == AnchorAnim.FastSpatial) if (type == AnchorAnim.FastSpatial)
return Appearance.anim.curves.expressiveFastSpatial; return Tokens.anim.curves.expressiveFastSpatial;
if (type == AnchorAnim.DefaultSpatial) if (type == AnchorAnim.DefaultSpatial)
return Appearance.anim.curves.expressiveDefaultSpatial; return Tokens.anim.curves.expressiveDefaultSpatial;
if (type == AnchorAnim.SlowSpatial) if (type == AnchorAnim.SlowSpatial)
return Appearance.anim.curves.expressiveSlowSpatial; return Tokens.anim.curves.expressiveSlowSpatial;
if (type >= AnchorAnim.StandardSmall && type <= AnchorAnim.StandardExtraLarge) if (type >= AnchorAnim.StandardSmall && type <= AnchorAnim.StandardExtraLarge)
return Appearance.anim.curves.standard; return Tokens.anim.curves.standard;
if (type >= AnchorAnim.EmphasizedSmall && type <= AnchorAnim.EmphasizedExtraLarge) if (type >= AnchorAnim.EmphasizedSmall && type <= AnchorAnim.EmphasizedExtraLarge)
return Appearance.anim.curves.emphasized; return Tokens.anim.curves.emphasized;
return Appearance.anim.curves.expressiveDefaultSpatial; return Tokens.anim.curves.expressiveDefaultSpatial;
} }
} }
+17 -17
View File
@@ -1,5 +1,5 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
NumberAnimation { NumberAnimation {
enum Type { enum Type {
@@ -23,41 +23,41 @@ NumberAnimation {
duration: { duration: {
if (type < Anim.StandardSmall || type > Anim.SlowEffects) if (type < Anim.StandardSmall || type > Anim.SlowEffects)
return Appearance.anim.durations.normal; return Tokens.anim.durations.normal;
if (type === Anim.FastSpatial) if (type === Anim.FastSpatial)
return Appearance.anim.durations.expressiveFastSpatial; return Tokens.anim.durations.expressiveFastSpatial;
if (type === Anim.DefaultSpatial) if (type === Anim.DefaultSpatial)
return Appearance.anim.durations.expressiveDefaultSpatial; return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial) if (type === Anim.SlowSpatial)
return Appearance.anim.durations.large; return Tokens.anim.durations.large;
if (type === Anim.FastEffects) if (type === Anim.FastEffects)
return Appearance.anim.durations.expressiveFastEffects; return Tokens.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects) if (type === Anim.DefaultEffects)
return Appearance.anim.durations.expressiveEffects; return Tokens.anim.durations.expressiveEffects;
if (type === Anim.SlowEffects) if (type === Anim.SlowEffects)
return Appearance.anim.durations.expressiveSlowEffects; return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"]; const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; const idx = type % 4;
return Appearance.anim.durations[types[idx]]; return Tokens.anim.durations[types[idx]];
} }
easing.bezierCurve: { easing.bezierCurve: {
if (type === Anim.FastSpatial) if (type === Anim.FastSpatial)
return Appearance.anim.curves.expressiveFastSpatial; return Tokens.anim.curves.expressiveFastSpatial;
if (type === Anim.DefaultSpatial) if (type === Anim.DefaultSpatial)
return Appearance.anim.curves.expressiveDefaultSpatial; return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial) if (type === Anim.SlowSpatial)
return Appearance.anim.curves.expressiveSlowSpatial; return Tokens.anim.curves.expressiveSlowSpatial;
if (type === Anim.FastEffects) if (type === Anim.FastEffects)
return Appearance.anim.curves.expressiveFastEffects; return Tokens.anim.curves.expressiveFastEffects;
if (type === Anim.DefaultEffects) if (type === Anim.DefaultEffects)
return Appearance.anim.curves.expressiveDefaultEffects; return Tokens.anim.curves.expressiveDefaultEffects;
if (type === Anim.SlowEffects) if (type === Anim.SlowEffects)
return Appearance.anim.curves.expressiveSlowEffects; return Tokens.anim.curves.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge) if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Appearance.anim.curves.emphasized; return Tokens.anim.curves.emphasized;
return Appearance.anim.curves.standard; return Tokens.anim.curves.standard;
} }
} }
+15 -14
View File
@@ -1,11 +1,12 @@
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates
import qs.Config import ZShell.Config
import qs.Services
Slider { Slider {
id: root id: root
property color color: DynamicColors.palette.m3secondary property color color: Colors.palette.m3secondary
required property string icon required property string icon
property bool initialized: false property bool initialized: false
readonly property bool isHorizontal: orientation === Qt.Horizontal readonly property bool isHorizontal: orientation === Qt.Horizontal
@@ -19,9 +20,9 @@ Slider {
background: CustomRect { background: CustomRect {
id: groove id: groove
color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, 2) color: Colors.layer(Colors.palette.m3surfaceContainer, 2)
height: root.availableHeight height: root.availableHeight
radius: Appearance.rounding.full radius: Tokens.rounding.full
width: root.availableWidth width: root.availableWidth
x: root.leftPadding x: root.leftPadding
y: root.topPadding y: root.topPadding
@@ -62,8 +63,8 @@ Slider {
id: rect id: rect
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3inverseSurface color: Colors.palette.m3inverseSurface
radius: Appearance.rounding.full radius: Tokens.rounding.full
MouseArea { MouseArea {
id: handleInteraction id: handleInteraction
@@ -82,12 +83,12 @@ Slider {
function update(): void { function update(): void {
animate = !moving; animate = !moving;
binding.when = moving; binding.when = moving;
font.pointSize = moving ? Appearance.font.size.small : Appearance.font.size.larger; font.pointSize = moving ? Tokens.font.size.small : Tokens.font.size.larger;
font.family = moving ? Appearance.font.family.sans : Appearance.font.family.material; font.family = moving ? Config.appearance.font.family.sans : Config.appearance.font.family.material;
} }
anchors.centerIn: parent anchors.centerIn: parent
color: DynamicColors.palette.m3inverseOnSurface color: Colors.palette.m3inverseOnSurface
text: root.icon text: root.icon
onMovingChanged: anim.restart() onMovingChanged: anim.restart()
@@ -105,8 +106,8 @@ Slider {
id: anim id: anim
Anim { Anim {
duration: Appearance.anim.durations.normal / 2 duration: Tokens.anim.durations.normal / 2
easing.bezierCurve: Appearance.anim.curves.standardAccel easing.bezierCurve: Tokens.anim.curves.standardAccel
property: "scale" property: "scale"
target: icon target: icon
to: 0 to: 0
@@ -117,8 +118,8 @@ Slider {
} }
Anim { Anim {
duration: Appearance.anim.durations.normal / 2 duration: Tokens.anim.durations.normal / 2
easing.bezierCurve: Appearance.anim.curves.standardDecel easing.bezierCurve: Tokens.anim.curves.standardDecel
property: "scale" property: "scale"
target: icon target: icon
to: 1 to: 1
@@ -129,7 +130,7 @@ Slider {
} }
Behavior on value { Behavior on value {
Anim { Anim {
duration: Appearance.anim.durations.large duration: Tokens.anim.durations.large
} }
} }
+10 -9
View File
@@ -1,5 +1,6 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
import qs.Services
CustomRect { CustomRect {
id: root id: root
@@ -13,14 +14,14 @@ CustomRect {
property color activeColor property color activeColor
property color activeOnColor property color activeOnColor
property bool checked property bool checked
property real checkedRadius: Appearance.rounding.medium property real checkedRadius: Tokens.rounding.medium
property real defaultRadius: Appearance.rounding.large property real defaultRadius: Tokens.rounding.large
property color disabledColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.1) property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
property color disabledOnColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.38) property color disabledOnColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
property bool fillWidth property bool fillWidth
property font font: ({ property font font: ({
family: Appearance.font.family.sans, family: Config.appearance.font.family.sans,
pointSize: Appearance.font.size.larger, pointSize: Tokens.font.size.larger,
bold: false bold: false
}) })
property real horizontalPadding: padding property real horizontalPadding: padding
@@ -35,7 +36,7 @@ CustomRect {
readonly property color onColor: !enabled ? disabledOnColor : internalChecked ? activeOnColor : inactiveOnColor readonly property color onColor: !enabled ? disabledOnColor : internalChecked ? activeOnColor : inactiveOnColor
property real padding property real padding
readonly property alias pressed: stateLayer.pressed readonly property alias pressed: stateLayer.pressed
property real pressedRadius: Appearance.rounding.small property real pressedRadius: Tokens.rounding.smallest
readonly property alias radiusAnim: radiusAnim readonly property alias radiusAnim: radiusAnim
property bool radiusMorph: true property bool radiusMorph: true
property alias shapeMorph: stateLayer.shapeMorph property alias shapeMorph: stateLayer.shapeMorph
@@ -53,7 +54,7 @@ CustomRect {
if (internalChecked) if (internalChecked)
return checkedRadius; return checkedRadius;
if (isRound) if (isRound)
return (height || implicitHeight) / 2 * Math.min(1, Appearance.rounding.scale); return (height || implicitHeight) / 2 * Math.min(1, Tokens.rounding.scale);
return defaultRadius; return defaultRadius;
} }
+59 -4
View File
@@ -1,8 +1,63 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
ColorAnimation { ColorAnimation {
duration: MaterialEasing.standardTime enum Type {
easing.bezierCurve: MaterialEasing.standard StandardSmall = 0,
easing.type: Easing.BezierSpline Standard,
StandardLarge,
StandardExtraLarge,
EmphasizedSmall,
Emphasized,
EmphasizedLarge,
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: CAnim.DefaultSpatial
duration: {
if (type < CAnim.StandardSmall || type > Anim.SlowEffects)
return Tokens.anim.durations.normal;
if (type === CAnim.FastSpatial)
return Tokens.anim.durations.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.durations.large;
if (type === CAnim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.durations.expressiveEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4;
return Tokens.anim.durations[types[idx]];
}
easing.bezierCurve: {
if (type === CAnim.FastSpatial)
return Tokens.anim.curves.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.curves.expressiveSlowSpatial;
if (type === CAnim.FastEffects)
return Tokens.anim.curves.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.curves.expressiveDefaultEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.curves.expressiveSlowEffects;
if (type >= CAnim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.curves.emphasized;
return Tokens.anim.curves.standard;
}
} }
+9 -8
View File
@@ -1,7 +1,8 @@
import qs.Config import ZShell.Config
import ZShell.Internal import ZShell.Internal
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates
import qs.Services
BusyIndicator { BusyIndicator {
id: root id: root
@@ -17,12 +18,12 @@ BusyIndicator {
} }
property int animState property int animState
property color bgColor: DynamicColors.palette.m3secondaryContainer property color bgColor: Colors.palette.m3secondaryContainer
property color fgColor: DynamicColors.palette.m3primary property color fgColor: Colors.palette.m3primary
property real implicitSize: Appearance.font.size.normal * 3 property real implicitSize: Tokens.font.size.normal * 3
property real internalStrokeWidth: strokeWidth property real internalStrokeWidth: strokeWidth
readonly property alias progress: manager.progress readonly property alias progress: manager.progress
property real strokeWidth: Appearance.padding.small * 0.8 property real strokeWidth: Tokens.padding.small * 0.8
property alias type: manager.indeterminateAnimationType property alias type: manager.indeterminateAnimationType
implicitHeight: implicitSize implicitHeight: implicitSize
@@ -50,7 +51,7 @@ BusyIndicator {
} }
transitions: Transition { transitions: Transition {
Anim { Anim {
duration: manager.completeEndDuration * Appearance.anim.durations.scale duration: manager.completeEndDuration * Tokens.anim.durations.scale
properties: "opacity,internalStrokeWidth" properties: "opacity,internalStrokeWidth"
} }
} }
@@ -76,7 +77,7 @@ BusyIndicator {
} }
NumberAnimation { NumberAnimation {
duration: manager.duration * Appearance.anim.durations.scale duration: manager.duration * Tokens.anim.durations.scale
from: 0 from: 0
loops: Animation.Infinite loops: Animation.Infinite
property: "progress" property: "progress"
@@ -86,7 +87,7 @@ BusyIndicator {
} }
NumberAnimation { NumberAnimation {
duration: manager.completeEndDuration * Appearance.anim.durations.scale duration: manager.completeEndDuration * Tokens.anim.durations.scale
from: 0 from: 0
property: "completeEndProgress" property: "completeEndProgress"
running: root.animState === CircularIndicator.Completing running: root.animState === CircularIndicator.Completing
+7 -6
View File
@@ -3,24 +3,25 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Shapes import QtQuick.Shapes
import ZShell.Components import ZShell.Components
import qs.Config import ZShell.Config
import qs.Services
Item { Item {
id: root id: root
readonly property real arcRadius: (size - padding - strokeWidth * (1 + waveAmplitude * 2)) / 2 readonly property real arcRadius: (size - padding - strokeWidth * (1 + waveAmplitude * 2)) / 2
property color bgColor: DynamicColors.palette.m3secondaryContainer property color bgColor: Colors.palette.m3secondaryContainer
property real clampedVal: Math.max(1 / 360, Math.min(1, isNaN(value) ? 0 : value)) property real clampedVal: Math.max(1 / 360, Math.min(1, isNaN(value) ? 0 : value))
readonly property real dotAngleRad: (startAngle + sweepAngle - gapAngle * (sweepAngle < 360 ? 0 : 1)) * Math.PI / 180 readonly property real dotAngleRad: (startAngle + sweepAngle - gapAngle * (sweepAngle < 360 ? 0 : 1)) * Math.PI / 180
property color fgColor: DynamicColors.palette.m3primary property color fgColor: Colors.palette.m3primary
readonly property real gapAngle: ((spacing + strokeWidth) / (arcRadius || 1)) * (180 / Math.PI) readonly property real gapAngle: ((spacing + strokeWidth) / (arcRadius || 1)) * (180 / Math.PI)
property alias hasEndIndicator: dot.active property alias hasEndIndicator: dot.active
property real implicitSize property real implicitSize
property int padding: 0 property int padding: 0
readonly property real size: Math.min(width, height) readonly property real size: Math.min(width, height)
property int spacing: Appearance.spacing.small property int spacing: Tokens.spacing.small
property int startAngle: -90 property int startAngle: -90
property int strokeWidth: Appearance.padding.small property int strokeWidth: Tokens.padding.small
property int sweepAngle: 360 property int sweepAngle: 360
readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2 readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2
property real value property real value
@@ -110,7 +111,7 @@ Item {
implicitHeight: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth) implicitHeight: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth)
implicitWidth: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth) implicitWidth: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth)
opacity: Math.min(1, remainingArc.sweepAngle) opacity: Math.min(1, remainingArc.sweepAngle)
radius: Appearance.rounding.full radius: Tokens.rounding.full
} }
} }
} }
-135
View File
@@ -1,135 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Config
ColumnLayout {
id: root
default property alias content: contentColumn.data
property string description: ""
property bool expanded: false
property bool nested: false
property bool showBackground: false
required property string title
signal toggleRequested
Layout.fillWidth: true
spacing: Appearance.spacing.small
Item {
id: sectionHeaderItem
Layout.fillWidth: true
Layout.preferredHeight: Math.max(titleRow.implicitHeight + Appearance.padding.normal * 2, 48)
RowLayout {
id: titleRow
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.normal
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.normal
CustomText {
font.pointSize: Appearance.font.size.larger
font.weight: 500
text: root.title
}
Item {
Layout.fillWidth: true
}
MaterialIcon {
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal
rotation: root.expanded ? 180 : 0
text: "expand_more"
Behavior on rotation {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
}
StateLayer {
anchors.fill: parent
color: DynamicColors.palette.m3onSurface
radius: Appearance.rounding.normal
showHoverBackground: false
onClicked: {
root.toggleRequested();
root.expanded = !root.expanded;
}
}
}
Item {
id: contentWrapper
Layout.fillWidth: true
Layout.preferredHeight: root.expanded ? (contentColumn.implicitHeight + Appearance.spacing.small * 2) : 0
clip: true
Behavior on Layout.preferredHeight {
Anim {
easing.bezierCurve: Appearance.anim.curves.standard
}
}
CustomRect {
id: backgroundRect
anchors.fill: parent
color: DynamicColors.transparency.enabled ? DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, root.nested ? 3 : 2) : (root.nested ? DynamicColors.palette.m3surfaceContainerHigh : DynamicColors.palette.m3surfaceContainer)
opacity: root.showBackground && root.expanded ? 1.0 : 0.0
radius: Appearance.rounding.normal
visible: root.showBackground
Behavior on opacity {
Anim {
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
ColumnLayout {
id: contentColumn
anchors.bottomMargin: Appearance.spacing.small
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.normal
opacity: root.expanded ? 1.0 : 0.0
spacing: Appearance.spacing.small
y: Appearance.spacing.small
Behavior on opacity {
Anim {
easing.bezierCurve: Appearance.anim.curves.standard
}
}
CustomText {
id: descriptionText
Layout.bottomMargin: root.description !== "" ? Appearance.spacing.small : 0
Layout.fillWidth: true
Layout.topMargin: root.description !== "" ? Appearance.spacing.smaller : 0
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.small
text: root.description
visible: root.description !== ""
wrapMode: Text.Wrap
}
}
}
}
+7 -6
View File
@@ -1,7 +1,8 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import qs.Config import ZShell.Config
import qs.Services
Item { Item {
id: root id: root
@@ -18,9 +19,9 @@ Item {
property real lastChromaticHue: 0 property real lastChromaticHue: 0
readonly property real radius: (Math.min(width, height) - handleSize) / 2 readonly property real radius: (Math.min(width, height) - handleSize) / 2
readonly property int segmentCount: 240 readonly property int segmentCount: 240
readonly property color thumbColor: DynamicColors.palette.m3inverseSurface readonly property color thumbColor: Colors.palette.m3inverseSurface
readonly property color thumbContentColor: DynamicColors.palette.m3inverseOnSurface readonly property color thumbContentColor: Colors.palette.m3inverseOnSurface
readonly property color trackColor: DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, 2) readonly property color trackColor: Colors.layer(Colors.palette.m3surfaceContainer, 2)
function hueToAngle(hue) { function hueToAngle(hue) {
return arcStartAngle + arcSweep * hue; return arcStartAngle + arcSweep * hue;
@@ -153,8 +154,8 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
color: root.drawing?.drawingState.penColor color: root.drawing?.drawingState.penColor
implicitHeight: implicitWidth implicitHeight: implicitWidth
implicitWidth: canvas.height - root.handleSize - Appearance.padding.extraLarge * 2 implicitWidth: canvas.height - root.handleSize - Tokens.padding.extraLarge * 2
radius: Appearance.rounding.full radius: Tokens.rounding.full
Behavior on color { Behavior on color {
enabled: false enabled: false
-70
View File
@@ -1,70 +0,0 @@
import QtQuick
import QtQuick.Templates
import qs.Config
Slider {
id: root
property color nonPeakColor: DynamicColors.tPalette.m3primary
required property real peak
property color peakColor: DynamicColors.palette.m3primary
background: Item {
CustomRect {
anchors.bottom: parent.bottom
anchors.bottomMargin: root.implicitHeight / 3
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: root.implicitHeight / 3
bottomRightRadius: root.implicitHeight / 15
color: root.nonPeakColor
implicitWidth: root.handle.x - root.implicitHeight
radius: Appearance.rounding.full
topRightRadius: root.implicitHeight / 15
CustomRect {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: parent.top
bottomRightRadius: root.implicitHeight / 15
color: root.peakColor
implicitWidth: parent.width * root.peak
radius: Appearance.rounding.full
topRightRadius: root.implicitHeight / 15
Behavior on implicitWidth {
Anim {
duration: 50
}
}
}
}
CustomRect {
anchors.bottom: parent.bottom
anchors.bottomMargin: root.implicitHeight / 3
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: root.implicitHeight / 3
bottomLeftRadius: root.implicitHeight / 15
color: DynamicColors.tPalette.m3surfaceContainer
implicitWidth: root.implicitWidth - root.handle.x - root.handle.implicitWidth - root.implicitHeight
radius: Appearance.rounding.full
topLeftRadius: root.implicitHeight / 15
}
}
handle: CustomRect {
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3primary
implicitHeight: 15
implicitWidth: 5
radius: Appearance.rounding.full
x: root.visualPosition * root.availableWidth - implicitWidth / 2
MouseArea {
acceptedButtons: Qt.NoButton
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
}
}
}
-69
View File
@@ -1,69 +0,0 @@
import QtQuick
import QtQuick.Controls.Basic
BusyIndicator {
id: control
property int busySize: 64
property color color: delegate.color
contentItem: Item {
implicitHeight: control.busySize
implicitWidth: control.busySize
Item {
id: item
height: control.busySize
opacity: control.running ? 1 : 0
width: control.busySize
x: parent.width / 2 - (control.busySize / 2)
y: parent.height / 2 - (control.busySize / 2)
Behavior on opacity {
OpacityAnimator {
duration: 250
}
}
RotationAnimator {
duration: 1250
from: 0
loops: Animation.Infinite
running: control.visible && control.running
target: item
to: 360
}
Repeater {
id: repeater
model: 6
CustomRect {
id: delegate
required property int index
color: control.color
implicitHeight: 10
implicitWidth: 10
radius: 5
x: item.width / 2 - width / 2
y: item.height / 2 - height / 2
transform: [
Translate {
y: -Math.min(item.width, item.height) * 0.5 + 5
},
Rotation {
angle: delegate.index / repeater.count * 360
origin.x: 5
origin.y: 5
}
]
}
}
}
}
}
-32
View File
@@ -1,32 +0,0 @@
import QtQuick
import QtQuick.Controls
import qs.Config
Button {
id: control
property color bgColor: DynamicColors.palette.m3primary
property int radius: Appearance.rounding.smallest / 2
property color textColor: DynamicColors.palette.m3onPrimary
background: CustomRect {
color: control.bgColor
opacity: control.enabled ? 1.0 : 0.5
radius: control.radius
}
contentItem: CustomText {
color: control.textColor
horizontalAlignment: Text.AlignHCenter
opacity: control.enabled ? 1.0 : 0.5
text: control.text
verticalAlignment: Text.AlignVCenter
}
StateLayer {
radius: control.radius
onClicked: {
control.clicked();
}
}
}
+6 -5
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import qs.Config import ZShell.Config
import qs.Services
CheckBox { CheckBox {
id: control id: control
@@ -18,14 +19,14 @@ CheckBox {
indicator: CustomRect { indicator: CustomRect {
// x: control.leftPadding // x: control.leftPadding
// y: parent.implicitHeight / 2 - implicitHeight / 2 // y: parent.implicitHeight / 2 - implicitHeight / 2
border.color: control.checked ? DynamicColors.palette.m3primary : "transparent" border.color: control.checked ? Colors.palette.m3primary : "transparent"
color: DynamicColors.palette.m3surfaceVariant color: Colors.palette.m3surfaceVariant
implicitHeight: control.checkHeight implicitHeight: control.checkHeight
implicitWidth: control.checkWidth implicitWidth: control.checkWidth
radius: Appearance.rounding.smallest / 2 radius: Tokens.rounding.smallest / 2
CustomRect { CustomRect {
color: DynamicColors.palette.m3primary color: Colors.palette.m3primary
implicitHeight: control.checkHeight - (y * 2) implicitHeight: control.checkHeight - (y * 2)
implicitWidth: control.checkWidth - (x * 2) implicitWidth: control.checkWidth - (x * 2)
radius: 3 radius: 3
-169
View File
@@ -1,169 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import qs.Config
ComboBox {
id: root
property int cornerRadius: Appearance.rounding.normal
property int fieldHeight: 42
property bool filled: true
property real focusRingOpacity: 0.70
property int hPadding: 16
property int menuCornerRadius: 16
property int menuRowHeight: 46
property int menuVisibleRows: 7
property bool preferPopupWindow: false
hoverEnabled: true
implicitHeight: fieldHeight
implicitWidth: 240
spacing: 8
// ---------- Field background (filled/outlined + state layers + focus ring) ----------
background: Item {
anchors.fill: parent
CustomRect {
id: container
anchors.fill: parent
color: DynamicColors.palette.m3surfaceVariant
radius: root.cornerRadius
StateLayer {
}
}
}
// ---------- Content ----------
contentItem: RowLayout {
anchors.fill: parent
anchors.leftMargin: root.hPadding
anchors.rightMargin: root.hPadding
spacing: 12
// Display text
CustomText {
Layout.fillWidth: true
color: root.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSurfaceVariant
elide: Text.ElideRight
font.pixelSize: 16
font.weight: Font.Medium
text: root.currentText
verticalAlignment: Text.AlignVCenter
}
// Indicator chevron (simple, replace with your icon system)
CustomText {
color: root.enabled ? DynamicColors.palette.m3onSurfaceVariant : DynamicColors.palette.m3onSurfaceVariant
rotation: root.popup.visible ? 180 : 0
text: "▾"
transformOrigin: Item.Center
verticalAlignment: Text.AlignVCenter
Behavior on rotation {
NumberAnimation {
duration: 140
easing.type: Easing.OutCubic
}
}
}
}
popup: Popup {
id: p
implicitHeight: list.contentItem.height + Appearance.padding.small * 2
implicitWidth: root.width
modal: true
popupType: root.preferPopupWindow ? Popup.Window : Popup.Item
y: -list.currentIndex * (root.menuRowHeight + Appearance.spacing.small) - Appearance.padding.small
background: CustomRect {
color: DynamicColors.palette.m3surface
radius: root.menuCornerRadius
}
contentItem: ListView {
id: list
anchors.bottomMargin: Appearance.padding.small
anchors.fill: parent
anchors.topMargin: Appearance.padding.small
clip: true
currentIndex: root.currentIndex
model: root.delegateModel
spacing: Appearance.spacing.small
delegate: CustomRect {
required property int index
required property var modelData
anchors.horizontalCenter: parent.horizontalCenter
color: (index === root.currentIndex) ? DynamicColors.palette.m3primary : "transparent"
implicitHeight: root.menuRowHeight
implicitWidth: p.implicitWidth - Appearance.padding.small * 2
radius: Appearance.rounding.normal - Appearance.padding.small
RowLayout {
anchors.fill: parent
spacing: 10
CustomText {
Layout.fillWidth: true
color: DynamicColors.palette.m3onSurface
elide: Text.ElideRight
font.pixelSize: 15
text: modelData
verticalAlignment: Text.AlignVCenter
}
CustomText {
color: DynamicColors.palette.m3onSurfaceVariant
text: "✓"
verticalAlignment: Text.AlignVCenter
visible: index === root.currentIndex
}
}
StateLayer {
onClicked: {
root.currentIndex = index;
p.close();
}
}
}
}
// Expressive-ish open/close motion: subtle scale+fade (tune to taste). :contentReference[oaicite:5]{index=5}
enter: Transition {
Anim {
from: 0
property: "opacity"
to: 1
}
Anim {
from: 0.98
property: "scale"
to: 1.0
}
}
exit: Transition {
Anim {
from: 1
property: "opacity"
to: 0
}
}
Elevation {
anchors.fill: parent
level: 2
radius: root.menuCornerRadius
z: -1
}
}
}
+18
View File
@@ -4,12 +4,30 @@ import qs.Helpers
Flickable { Flickable {
id: root id: root
property bool doneFakeFlick
interactive: !Visibilities.getForActive().isDrawing interactive: !Visibilities.getForActive().isDrawing
maximumFlickVelocity: 3000 maximumFlickVelocity: 3000
rebound: Transition { rebound: Transition {
onRunningChanged: {
if (!running && !root.doneFakeFlick) {
root.doneFakeFlick = true;
root.flick(1, 1);
root.flick(-1, -1);
Qt.callLater(() => root.cancelFlick());
}
}
Anim { Anim {
properties: "x,y" properties: "x,y"
} }
} }
Timer {
interval: 10
running: root.doneFakeFlick
onTriggered: root.doneFakeFlick = false
}
} }
+1 -1
View File
@@ -6,7 +6,7 @@ ListView {
property bool doneFakeFlick property bool doneFakeFlick
interactive: !Visibilities.getForActive().isDrawing interactive: !Visibilities.getForActive()?.isDrawing
maximumFlickVelocity: 3000 maximumFlickVelocity: 3000
rebound: Transition { rebound: Transition {
+8 -7
View File
@@ -5,7 +5,8 @@ import QtQuick.Templates
import ZShell import ZShell
import ZShell.Components import ZShell.Components
import ZShell.Internal import ZShell.Internal
import qs.Config import ZShell.Config
import qs.Services
ProgressBar { ProgressBar {
id: root id: root
@@ -16,8 +17,8 @@ ProgressBar {
Stopped Stopped
} }
property color bgColor: DynamicColors.palette.m3secondaryContainer property color bgColor: Colors.palette.m3secondaryContainer
property color fgColor: DynamicColors.palette.m3primary property color fgColor: Colors.palette.m3primary
property int indeterminateAnimState: CustomProgressBar.Stopped property int indeterminateAnimState: CustomProgressBar.Stopped
property real waveAmplitude: 0.5 property real waveAmplitude: 0.5
property int waveDuration: 1000 property int waveDuration: 1000
@@ -64,7 +65,7 @@ ProgressBar {
LinearIndicatorManager { LinearIndicatorManager {
id: manager id: manager
gap: Appearance.spacing.extraSmall gap: Tokens.spacing.extraSmall
Anim on completeEndProgress { Anim on completeEndProgress {
duration: manager.completeEndDuration duration: manager.completeEndDuration
@@ -94,7 +95,7 @@ ProgressBar {
id: remaining id: remaining
anchors.right: parent.right anchors.right: parent.right
implicitWidth: parent.width - wave.implicitWidth - Appearance.spacing.extraSmall implicitWidth: parent.width - wave.implicitWidth - Tokens.spacing.extraSmall
} }
Line { Line {
@@ -106,7 +107,7 @@ ProgressBar {
color: root.fgColor color: root.fgColor
implicitHeight: implicitSize implicitHeight: implicitSize
implicitWidth: implicitSize implicitWidth: implicitSize
radius: Appearance.rounding.full radius: Tokens.rounding.full
Behavior on implicitSize { Behavior on implicitSize {
Anim { Anim {
@@ -200,7 +201,7 @@ ProgressBar {
color: root.bgColor color: root.bgColor
implicitHeight: parent.height implicitHeight: parent.height
implicitWidth: bounds.y - bounds.x implicitWidth: bounds.y - bounds.x
radius: Appearance.rounding.full radius: Tokens.rounding.full
x: bounds.x x: bounds.x
} }
component Wave: WavyLine { component Wave: WavyLine {
+8 -7
View File
@@ -1,11 +1,12 @@
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates
import qs.Config import ZShell.Config
import qs.Services
RadioButton { RadioButton {
id: root id: root
font.pointSize: Appearance.font.size.normal font.pointSize: Tokens.font.size.normal
implicitHeight: Math.max(implicitIndicatorHeight, implicitContentHeight) implicitHeight: Math.max(implicitIndicatorHeight, implicitContentHeight)
implicitWidth: implicitIndicatorWidth + implicitContentWidth + contentItem.anchors.leftMargin implicitWidth: implicitIndicatorWidth + implicitContentWidth + contentItem.anchors.leftMargin
@@ -20,12 +21,12 @@ RadioButton {
id: outerCircle id: outerCircle
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
border.color: root.checked ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant border.color: root.checked ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
border.width: 2 border.width: 2
color: "transparent" color: "transparent"
implicitHeight: 16 implicitHeight: 16
implicitWidth: 16 implicitWidth: 16
radius: Appearance.rounding.full radius: Tokens.rounding.full
Behavior on border.color { Behavior on border.color {
CAnim { CAnim {
@@ -34,7 +35,7 @@ RadioButton {
StateLayer { StateLayer {
anchors.margins: -7 anchors.margins: -7
color: root.checked ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3primary color: root.checked ? Colors.palette.m3onSurface : Colors.palette.m3primary
z: -1 z: -1
onClicked: { onClicked: {
@@ -44,10 +45,10 @@ RadioButton {
CustomRect { CustomRect {
anchors.centerIn: parent anchors.centerIn: parent
color: Qt.alpha(DynamicColors.palette.m3primary, root.checked ? 1 : 0) color: Qt.alpha(Colors.palette.m3primary, root.checked ? 1 : 0)
implicitHeight: 8 implicitHeight: 8
implicitWidth: 8 implicitWidth: 8
radius: Appearance.rounding.full radius: Tokens.rounding.full
} }
} }
} }
+7 -6
View File
@@ -1,7 +1,8 @@
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates
import qs.Helpers import qs.Helpers
import qs.Config import ZShell.Config
import qs.Services
ScrollBar { ScrollBar {
id: root id: root
@@ -17,7 +18,7 @@ ScrollBar {
readonly property real travelScale: root.rawTravel > 0 ? root.effectiveTravel / root.rawTravel : 0 readonly property real travelScale: root.rawTravel > 0 ? root.effectiveTravel / root.rawTravel : 0
enabled: !Visibilities.getForActive().isDrawing enabled: !Visibilities.getForActive().isDrawing
implicitWidth: Appearance.padding.extraSmall * 2 implicitWidth: Tokens.padding.extraSmall * 2
contentItem: Item { contentItem: Item {
} }
@@ -51,15 +52,15 @@ ScrollBar {
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
implicitWidth: handle.implicitWidth implicitWidth: handle.implicitWidth
radius: Appearance.rounding.full radius: Tokens.rounding.full
CustomRect { CustomRect {
id: handle id: handle
anchors.right: parent.right anchors.right: parent.right
color: DynamicColors.palette.m3secondary color: Colors.palette.m3secondary
implicitHeight: root.height * root.effectiveSize implicitHeight: root.height * root.effectiveSize
implicitWidth: fullMouse.pressed || fullMouse.containsMouse ? Appearance.padding.extraSmall * 2 : Appearance.padding.extraSmall implicitWidth: fullMouse.pressed || fullMouse.containsMouse ? Tokens.padding.extraSmall * 2 : Tokens.padding.extraSmall
opacity: { opacity: {
if (!root.enabled) if (!root.enabled)
return 0; return 0;
@@ -73,7 +74,7 @@ ScrollBar {
return 0.6; return 0.6;
return 0; return 0;
} }
radius: Appearance.rounding.full radius: Tokens.rounding.full
y: root.reversed ? root.height * (1 + root.nonAnimY) * root.travelScale : root.height * root.nonAnimY * root.travelScale y: root.reversed ? root.height * (1 + root.nonAnimY) * root.travelScale : root.height * root.nonAnimY * root.travelScale
Behavior on implicitWidth { Behavior on implicitWidth {
+17 -16
View File
@@ -5,20 +5,21 @@ import QtQuick.Templates
import ZShell.Components import ZShell.Components
import ZShell import ZShell
import qs.Components import qs.Components
import qs.Config import ZShell.Config
import qs.Services
Slider { Slider {
id: root id: root
property bool animateWave property bool animateWave
property color bgColor: enabled ? DynamicColors.palette.m3secondaryContainer : Qt.alpha(DynamicColors.palette.m3onSurface, 0.1) property color bgColor: enabled ? Colors.palette.m3secondaryContainer : Qt.alpha(Colors.palette.m3onSurface, 0.1)
property color fgColor: enabled ? DynamicColors.palette.m3primary : Qt.alpha(DynamicColors.palette.m3onSurface, 0.38) property color fgColor: enabled ? Colors.palette.m3primary : Qt.alpha(Colors.palette.m3onSurface, 0.38)
property real filledWidth property real filledWidth
property alias inset: inset property alias inset: inset
property color insetColor: enabled ? (inset.attached ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onPrimary) : DynamicColors.palette.m3onSurface property color insetColor: enabled ? (inset.attached ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onPrimary) : Colors.palette.m3onSurface
property string insetIcon: "" property string insetIcon: ""
property real pos: visualPosition property real pos: visualPosition
property int radius: Appearance.rounding.small property int radius: Tokens.rounding.small
property int waveDuration: 1000 property int waveDuration: 1000
property real waveFrequency: 6 property real waveFrequency: 6
property bool wavy property bool wavy
@@ -35,15 +36,15 @@ Slider {
id: remaining id: remaining
anchors.left: handle.right anchors.left: handle.right
anchors.leftMargin: Appearance.spacing.extraSmall anchors.leftMargin: Tokens.spacing.extraSmall
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
bottomLeftRadius: Appearance.rounding.extraSmall / 2 bottomLeftRadius: Tokens.rounding.extraSmall / 2
color: root.bgColor color: root.bgColor
implicitHeight: parent.height * (parent.height <= 12 ? opacity : Math.min(opacity * 2, 1)) implicitHeight: parent.height * (parent.height <= 12 ? opacity : Math.min(opacity * 2, 1))
opacity: Math.min(width, 12) / 12 opacity: Math.min(width, 12) / 12
radius: root.radius radius: root.radius
topLeftRadius: Appearance.rounding.extraSmall / 2 topLeftRadius: Tokens.rounding.extraSmall / 2
} }
CustomRect { CustomRect {
@@ -54,14 +55,14 @@ Slider {
implicitHeight: 4 * remaining.opacity implicitHeight: 4 * remaining.opacity
implicitWidth: implicitHeight implicitWidth: implicitHeight
opacity: remaining.opacity opacity: remaining.opacity
radius: Appearance.rounding.full radius: Tokens.rounding.full
} }
CustomRect { CustomRect {
id: handle id: handle
anchors.left: filled.right anchors.left: filled.right
anchors.leftMargin: Appearance.spacing.extraSmall anchors.leftMargin: Tokens.spacing.extraSmall
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: root.fgColor color: root.fgColor
implicitHeight: { implicitHeight: {
@@ -70,7 +71,7 @@ Slider {
return parent.height * (mouse.pressed ? lerp(3.5, 1.5) : lerp(3, 1.2)); return parent.height * (mouse.pressed ? lerp(3.5, 1.5) : lerp(3, 1.2));
} }
implicitWidth: 4 implicitWidth: 4
radius: Appearance.rounding.full radius: Tokens.rounding.full
Behavior on implicitHeight { Behavior on implicitHeight {
Anim { Anim {
@@ -91,17 +92,17 @@ Slider {
MaterialIcon { MaterialIcon {
id: inset id: inset
readonly property bool attached: root.width ? (root.width - handle.implicitWidth - handle.anchors.leftMargin) * root.pos < inset.paintedWidth + Appearance.spacing.extraSmall * 2 : false readonly property bool attached: root.width ? (root.width - handle.implicitWidth - handle.anchors.leftMargin) * root.pos < inset.paintedWidth + Tokens.spacing.extraSmall * 2 : false
property real dockT: attached ? 1 : 0 property real dockT: attached ? 1 : 0
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: parent.top anchors.top: parent.top
color: root.insetColor color: root.insetColor
font.pixelSize: Appearance.font.size.smaller * 2 font.pixelSize: Tokens.font.size.smaller * 2
text: root.insetIcon text: root.insetIcon
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
visible: !root.wavy && root.insetIcon !== "" visible: !root.wavy && root.insetIcon !== ""
x: Appearance.spacing.extraSmall + dockT * (handle.x + Appearance.spacing.small) x: Tokens.spacing.extraSmall + dockT * (handle.x + Tokens.spacing.small)
Behavior on dockT { Behavior on dockT {
Anim { Anim {
@@ -113,12 +114,12 @@ Slider {
id: lineComp id: lineComp
CustomRect { CustomRect {
bottomRightRadius: Appearance.rounding.extraSmall / 2 bottomRightRadius: Tokens.rounding.extraSmall / 2
color: root.fgColor color: root.fgColor
implicitHeight: root.height implicitHeight: root.height
implicitWidth: root.filledWidth implicitWidth: root.filledWidth
radius: root.radius radius: root.radius
topRightRadius: Appearance.rounding.extraSmall / 2 topRightRadius: Tokens.rounding.extraSmall / 2
} }
} }
+99 -134
View File
@@ -1,168 +1,133 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Templates
import qs.Config import ZShell.Config
import qs.Services
RowLayout { DoubleSpinBox {
id: root id: root
property string displayText: root.value.toString() property int cLayer: 1
property bool isEditing: false property int repeatDecay: 50
property real max: Infinity property int repeatRate: 400
property real min: -Infinity
property alias repeatRate: timer.interval
property real step: 1
property real value
signal valueModified(value: real) function decrease(): void {
let newValue = Math.max(from, value - stepSize);
spacing: Appearance.spacing.small const decimals = stepSize < 1 ? Math.max(1, Math.ceil(-Math.log10(stepSize))) : 0;
newValue = Math.round(newValue * Math.pow(10, decimals)) / Math.pow(10, decimals);
onValueChanged: { value = newValue;
if (!root.isEditing) { valueModified();
root.displayText = root.value.toString();
}
} }
CustomTextField { function increase(): void {
id: textField let newValue = Math.min(to, value + stepSize);
const decimals = stepSize < 1 ? Math.max(1, Math.ceil(-Math.log10(stepSize))) : 0;
newValue = Math.round(newValue * Math.pow(10, decimals)) / Math.pow(10, decimals);
value = newValue;
valueModified();
}
color: root.enabled ? DynamicColors.palette.m3onSurface : Qt.alpha(DynamicColors.palette.m3onSurface, 0.5) decimals: stepSize < 1 ? Math.max(1, Math.ceil(-Math.log10(stepSize))) : 0
implicitHeight: upButton.implicitHeight editable: true
implicitHeight: Math.max(up.indicator.implicitHeight, down.indicator.implicitHeight, contentItem.implicitHeight) + topPadding + bottomPadding
implicitWidth: contentItem.implicitWidth + leftPadding + rightPadding
leftPadding: up.indicator.implicitWidth + Tokens.spacing.extraSmall / 2
rightPadding: down.indicator.implicitWidth + Tokens.spacing.extraSmall / 2
spacing: Tokens.spacing.small
contentItem: TextFieldBase {
horizontalAlignment: TextField.AlignHCenter
implicitWidth: 65
inputMethodHints: Qt.ImhFormattedNumbersOnly inputMethodHints: Qt.ImhFormattedNumbersOnly
leftPadding: Appearance.padding.normal leftPadding: Tokens.padding.larger
padding: Appearance.padding.small readOnly: !root.editable
rightPadding: Appearance.padding.normal rightPadding: Tokens.padding.larger
text: root.isEditing ? text : root.displayText text: root.textFromValue(root.value, root.locale)
validator: root.validator
background: CustomRect { background: CustomRect {
color: root.enabled ? DynamicColors.tPalette.m3surfaceContainerHigh : DynamicColors.tPalette.m3surfaceContainerLow color: Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer)
implicitWidth: 100 radius: Tokens.rounding.extraSmall
radius: Appearance.rounding.full
}
validator: DoubleValidator {
bottom: root.min
decimals: root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0
top: root.max
}
onAccepted: {
const numValue = parseFloat(text);
if (!isNaN(numValue)) {
const clampedValue = Math.max(root.min, Math.min(root.max, numValue));
root.value = clampedValue;
root.displayText = clampedValue.toString();
root.valueModified(clampedValue);
} else {
text = root.displayText;
}
root.isEditing = false;
}
onActiveFocusChanged: {
if (activeFocus) {
root.isEditing = true;
} else {
root.isEditing = false;
root.displayText = root.value.toString();
}
}
onEditingFinished: {
if (text !== root.displayText) {
const numValue = parseFloat(text);
if (!isNaN(numValue)) {
const clampedValue = Math.max(root.min, Math.min(root.max, numValue));
root.value = clampedValue;
root.displayText = clampedValue.toString();
root.valueModified(clampedValue);
} else {
text = root.displayText;
}
}
root.isEditing = false;
} }
} }
down.indicator: IconButton {
id: downButton
CustomRect { bottomRightRadius: pressed ? Tokens.rounding.small : Tokens.rounding.extraSmall
color: enabled ? Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer) : disabledColor
disabledColor: Qt.alpha(Colors.palette.m3surfaceContainerHighest, 0.4)
icon: "remove"
isRound: true
label.anchors.horizontalCenterOffset: pressed ? 0 : 2
padding: Tokens.padding.extraSmall
topRightRadius: pressed ? Tokens.rounding.small : Tokens.rounding.extraSmall
type: IconButton.Text
Behavior on bottomRightRadius {
Anim {
type: Anim.DefaultEffects
}
}
Behavior on label.anchors.horizontalCenterOffset {
Anim {
type: Anim.DefaultEffects
}
}
Behavior on topRightRadius {
Anim {
type: Anim.DefaultEffects
}
}
}
up.indicator: IconButton {
id: upButton id: upButton
color: root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 1) anchors.right: parent.right
implicitHeight: upIcon.implicitHeight + Appearance.padding.small * 2 bottomLeftRadius: pressed ? Tokens.rounding.small : Tokens.rounding.extraSmall
implicitWidth: implicitHeight color: enabled ? Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer) : disabledColor
radius: Appearance.rounding.full disabledColor: Qt.alpha(Colors.palette.m3surfaceContainerHighest, 0.4)
icon: "add"
isRound: true
label.anchors.horizontalCenterOffset: pressed ? 0 : -2
padding: Tokens.padding.extraSmall
topLeftRadius: pressed ? Tokens.rounding.small : Tokens.rounding.extraSmall
type: IconButton.Text
StateLayer { Behavior on bottomLeftRadius {
id: upState Anim {
type: Anim.DefaultEffects
color: DynamicColors.palette.m3onPrimary
onClicked: {
let newValue = Math.min(root.max, root.value + root.step);
// Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
newValue = Math.round(newValue * Math.pow(10, decimals)) / Math.pow(10, decimals);
root.value = newValue;
root.displayText = newValue.toString();
root.valueModified(newValue);
} }
onPressAndHold: timer.start()
onReleased: timer.stop()
} }
Behavior on label.anchors.horizontalCenterOffset {
MaterialIcon { Anim {
id: upIcon type: Anim.DefaultEffects
anchors.centerIn: parent
color: root.enabled ? DynamicColors.palette.m3onPrimary : Qt.alpha(DynamicColors.palette.m3onSurface, 0.5)
text: "keyboard_arrow_up"
}
}
CustomRect {
color: root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 1)
implicitHeight: downIcon.implicitHeight + Appearance.padding.small * 2
implicitWidth: implicitHeight
radius: Appearance.rounding.full
StateLayer {
id: downState
color: DynamicColors.palette.m3onPrimary
onClicked: {
let newValue = Math.max(root.min, root.value - root.step);
// Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
newValue = Math.round(newValue * Math.pow(10, decimals)) / Math.pow(10, decimals);
root.value = newValue;
root.displayText = newValue.toString();
root.valueModified(newValue);
} }
onPressAndHold: timer.start()
onReleased: timer.stop()
} }
Behavior on topLeftRadius {
MaterialIcon { Anim {
id: downIcon type: Anim.DefaultEffects
}
anchors.centerIn: parent
color: root.enabled ? DynamicColors.palette.m3onPrimary : Qt.alpha(DynamicColors.palette.m3onSurface, 0.5)
text: "keyboard_arrow_down"
} }
} }
Timer { Timer {
id: timer id: timer
interval: 100 interval: root.repeatRate
repeat: true repeat: true
running: upButton.pressed || downButton.pressed
triggeredOnStart: true triggeredOnStart: true
onRunningChanged: {
if (!running)
interval = root.repeatRate;
}
onTriggered: { onTriggered: {
if (upState.pressed) if (upButton.pressed)
upState.onClicked(); root.increase();
else if (downState.pressed) else if (downButton.pressed)
downState.onClicked(); root.decrease();
if (interval > root.repeatDecay)
interval -= root.repeatDecay;
} }
} }
} }
+16 -15
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Config import ZShell.Config
import qs.Services
Row { Row {
id: root id: root
@@ -11,14 +12,14 @@ Row {
} }
property alias active: menu.active property alias active: menu.active
property color color: type == CustomSplitButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondaryContainer property color color: type == CustomSplitButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondaryContainer
property color disabledColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.1) property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
property color disabledTextColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.38) property color disabledTextColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
readonly property alias expandBtn: expandBtn readonly property alias expandBtn: expandBtn
property alias expanded: menu.expanded property alias expanded: menu.expanded
property string fallbackIcon property string fallbackIcon
property string fallbackText property string fallbackText
property real horizontalPadding: Appearance.padding.larger property real horizontalPadding: Tokens.padding.larger
readonly property alias iconLabel: iconLabel readonly property alias iconLabel: iconLabel
readonly property alias label: label readonly property alias label: label
readonly property alias menu: menu readonly property alias menu: menu
@@ -26,20 +27,20 @@ Row {
property bool menuOnTop property bool menuOnTop
property real minLeftWidth property real minLeftWidth
readonly property alias stateLayer: stateLayer readonly property alias stateLayer: stateLayer
property color textColor: type == CustomSplitButton.Filled ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondaryContainer property color textColor: type == CustomSplitButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondaryContainer
readonly property alias textRow: textRow readonly property alias textRow: textRow
property int type: CustomSplitButton.Filled property int type: CustomSplitButton.Filled
property real verticalPadding: Appearance.padding.small property real verticalPadding: Tokens.padding.small
spacing: Math.floor(Appearance.spacing.extraSmall) spacing: Math.floor(Tokens.spacing.extraSmall)
CustomRect { CustomRect {
bottomRightRadius: Appearance.rounding.small / 2 bottomRightRadius: Tokens.rounding.small / 2
color: !root.enabled ? root.disabledColor : root.color color: !root.enabled ? root.disabledColor : root.color
implicitHeight: expandBtn.implicitHeight implicitHeight: expandBtn.implicitHeight
implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2) implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2)
radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) radius: implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
topRightRadius: Appearance.rounding.small / 2 topRightRadius: Tokens.rounding.small / 2
StateLayer { StateLayer {
id: stateLayer id: stateLayer
@@ -57,7 +58,7 @@ Row {
anchors.centerIn: parent anchors.centerIn: parent
anchors.horizontalCenterOffset: Math.floor(root.verticalPadding / 4) anchors.horizontalCenterOffset: Math.floor(root.verticalPadding / 4)
spacing: Appearance.spacing.small spacing: Tokens.spacing.small
MaterialIcon { MaterialIcon {
id: iconLabel id: iconLabel
@@ -91,13 +92,13 @@ Row {
CustomRect { CustomRect {
id: expandBtn id: expandBtn
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) : Appearance.rounding.small / 2 property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) : Tokens.rounding.small / 2
bottomLeftRadius: rad bottomLeftRadius: rad
color: !root.enabled ? root.disabledColor : root.color color: !root.enabled ? root.disabledColor : root.color
implicitHeight: expandIcon.implicitHeight + root.verticalPadding * 2 implicitHeight: expandIcon.implicitHeight + root.verticalPadding * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) radius: implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
topLeftRadius: rad topLeftRadius: rad
Behavior on rad { Behavior on rad {
@@ -141,7 +142,7 @@ Row {
attachSideY: root.menuOnTop ? Menu.Top : Menu.Bottom attachSideY: root.menuOnTop ? Menu.Top : Menu.Bottom
attachTo: expandBtn attachTo: expandBtn
marginY: Appearance.spacing.small * (root.menuOnTop ? -1 : 1) marginY: Tokens.spacing.small * (root.menuOnTop ? -1 : 1)
thisSideY: root.menuOnTop ? Menu.Bottom : Menu.Top thisSideY: root.menuOnTop ? Menu.Bottom : Menu.Top
} }
} }
+7 -6
View File
@@ -2,7 +2,8 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Config import ZShell.Config
import qs.Services
Item { Item {
id: root id: root
@@ -21,7 +22,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
clip: false clip: false
implicitHeight: row.implicitHeight + Appearance.padding.smaller * 2 implicitHeight: row.implicitHeight + Tokens.padding.smaller * 2
opacity: shouldBeActive ? 1 : 0 opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8 scale: shouldBeActive ? 1 : 0.8
z: splitButton.menu.implicitHeight > 0 ? expandedZ : 1 z: splitButton.menu.implicitHeight > 0 ? expandedZ : 1
@@ -39,15 +40,15 @@ Item {
id: row id: row
anchors.left: parent.left anchors.left: parent.left
anchors.margins: Appearance.padding.small anchors.margins: Tokens.padding.small
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.normal spacing: Tokens.spacing.normal
CustomText { CustomText {
Layout.fillWidth: true Layout.fillWidth: true
color: root.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSurfaceVariant color: root.enabled ? Colors.palette.m3onSurface : Colors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.larger font.pointSize: Tokens.font.size.larger
text: root.label text: root.label
} }
+15 -14
View File
@@ -1,7 +1,8 @@
import QtQuick import QtQuick
import QtQuick.Shapes import QtQuick.Shapes
import QtQuick.Templates import QtQuick.Templates
import qs.Config import ZShell.Config
import qs.Services
Switch { Switch {
id: root id: root
@@ -12,20 +13,20 @@ Switch {
implicitWidth: implicitIndicatorWidth implicitWidth: implicitIndicatorWidth
indicator: CustomRect { indicator: CustomRect {
color: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, root.cLayer) color: root.checked && root.enabled ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer)
implicitHeight: Appearance.font.size.medium + Appearance.padding.normal * 2 implicitHeight: Tokens.font.size.medium + Tokens.padding.normal * 2
implicitWidth: implicitHeight * 1.7 implicitWidth: implicitHeight * 1.7
radius: Appearance.rounding.full radius: Tokens.rounding.full
CustomRect { CustomRect {
readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: root.checked && root.enabled ? DynamicColors.palette.m3onPrimary : DynamicColors.layer(DynamicColors.palette.m3outline, root.cLayer + 1) color: root.checked && root.enabled ? Colors.palette.m3onPrimary : Colors.layer(Colors.palette.m3outline, root.cLayer + 1)
implicitHeight: parent.implicitHeight - Appearance.padding.extraSmall implicitHeight: parent.implicitHeight - Tokens.padding.extraSmall
implicitWidth: nonAnimWidth implicitWidth: nonAnimWidth
radius: Appearance.rounding.full radius: Tokens.rounding.full
x: root.checked ? parent.implicitWidth - nonAnimWidth - Appearance.padding.extraSmall / 2 : Appearance.padding.extraSmall / 2 x: root.checked ? parent.implicitWidth - nonAnimWidth - Tokens.padding.extraSmall / 2 : Tokens.padding.extraSmall / 2
Behavior on implicitWidth { Behavior on implicitWidth {
Anim { Anim {
@@ -40,7 +41,7 @@ Switch {
CustomRect { CustomRect {
anchors.fill: parent anchors.fill: parent
color: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurface color: root.checked && root.enabled ? Colors.palette.m3primary : Colors.palette.m3onSurface
opacity: root.pressed ? 0.1 : root.hovered ? 0.08 : 0 opacity: root.pressed ? 0.1 : root.hovered ? 0.08 : 0
radius: parent.radius radius: parent.radius
@@ -91,7 +92,7 @@ Switch {
anchors.centerIn: parent anchors.centerIn: parent
asynchronous: true asynchronous: true
height: parent.implicitHeight - Appearance.padding.larger height: parent.implicitHeight - Tokens.padding.larger
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
width: height width: height
@@ -117,8 +118,8 @@ Switch {
fillColor: "transparent" fillColor: "transparent"
startX: icon.start1.x startX: icon.start1.x
startY: icon.start1.y startY: icon.start1.y
strokeColor: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3surfaceContainerHighest strokeColor: root.checked && root.enabled ? Colors.palette.m3primary : Colors.palette.m3surfaceContainerHighest
strokeWidth: Appearance.font.size.larger * 0.15 strokeWidth: Tokens.font.size.larger * 0.15
Behavior on strokeColor { Behavior on strokeColor {
CAnim { CAnim {
@@ -151,7 +152,7 @@ Switch {
} }
component PropAnim: PropertyAnimation { component PropAnim: PropertyAnimation {
duration: Appearance.anim.durations.expressiveFastSpatial duration: Tokens.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
} }
} }
+6 -5
View File
@@ -1,7 +1,8 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import qs.Config import ZShell.Config
import qs.Services
Text { Text {
id: root id: root
@@ -12,10 +13,10 @@ Text {
property string animateProp: "scale" property string animateProp: "scale"
property real animateTo: 1 property real animateTo: 1
color: DynamicColors.palette.m3onSurface color: Colors.palette.m3onSurface
font.family: Appearance.font.family.sans font.family: Config.appearance.font.family.sans
font.pointSize: Appearance.font.size.normal font.pointSize: Tokens.font.size.normal
linkColor: DynamicColors.palette.m3onPrimaryFixedVariant linkColor: Colors.palette.m3onPrimaryFixedVariant
renderType: Text.NativeRendering renderType: Text.NativeRendering
textFormat: Text.PlainText textFormat: Text.PlainText
+272 -48
View File
@@ -1,77 +1,301 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Shapes
import qs.Config import ZShell.Config
import qs.Services
TextField { TextFieldBase {
id: root id: root
property int cursorHeight: root.height enum TextFieldType {
Outlined,
Filled
}
background: null readonly property int clampedRadius: Math.min(horizontalPadding, Math.min(width, height) / 2, radius)
color: DynamicColors.palette.m3onSurface readonly property string effectiveSupportingText: isError && errorText ? errorText : supportingText
cursorVisible: !readOnly property bool emptyIsValid: true
font.family: Appearance.font.family.sans property string errorText
font.pointSize: Appearance.font.size.smaller readonly property int filledOffset: type === CustomTextField.Filled ? Tokens.spacing.small : 0
placeholderTextColor: DynamicColors.palette.m3outline readonly property int horizontalPadding: Tokens.padding.large
renderType: echoMode === TextField.Password ? TextField.QtRendering : TextField.NativeRendering property bool isError
property string leadingIcon
readonly property int leadingOffset: leadingIcon ? leadingIconLoader.width + leadingIconLoader.anchors.leftMargin : 0
property int radius: Tokens.rounding.small
readonly property real smallFontScale: smallFontSize / font.pointSize
property int smallFontSize: Tokens.font.size.small
property string supportingText
readonly property int supportingTextOffset: effectiveSupportingText ? supportingTextLoader.height + Tokens.spacing.extraSmall : 0
property string trailingIcon
readonly property int trailingOffset: trailingIcon ? trailingIconLoader.width + trailingIconLoader.anchors.rightMargin : 0
property int type: CustomTextField.Outlined
readonly property bool valid: !validate || (!text && emptyIsValid) || (validate instanceof RegExp ? validate.test(text) : !!validate(text))
property var validate // Regex or function
Behavior on color { bottomPadding: Tokens.padding.large + supportingTextOffset - filledOffset
CAnim { leftPadding: horizontalPadding + leadingOffset
rightPadding: horizontalPadding + trailingOffset
topPadding: Tokens.padding.large + filledOffset
background: Loader {
anchors.bottomMargin: root.supportingTextOffset
anchors.fill: parent
sourceComponent: root.type === CustomTextField.Filled ? filledComp : outlineComp
StateLayer {
id: stateLayer
cursorShape: Qt.IBeamCursor
enabled: !root.activeFocus
manualPressOverride: tapHandler.pressed
radius: root.type === CustomTextField.Outlined ? root.clampedRadius : 0
topLeftRadius: root.clampedRadius
topRightRadius: root.clampedRadius
onClicked: root.focus = true
} }
} }
cursorDelegate: CustomRect {
id: cursor
property bool disableBlink onEditingFinished: {
if (!valid)
isError = true;
}
onPressed: {
if (stateLayer.enabled)
stateLayer.press(stateLayer.mouseX, stateLayer.mouseY);
}
onTextEdited: {
if (isError)
isError = false;
}
color: DynamicColors.palette.m3primary Item {
implicitWidth: 2 id: contentWrapper
radius: Appearance.rounding.normal
Behavior on opacity { anchors.bottomMargin: root.supportingTextOffset
Anim { anchors.fill: parent
duration: Appearance.anim.durations.small
}
}
Connections { CustomText {
function onCursorPositionChanged(): void { id: placeholder
if (root.activeFocus && root.cursorVisible) {
cursor.opacity = 1; anchors.left: parent.left
cursor.disableBlink = true; anchors.leftMargin: root.leftPadding
enableBlink.restart(); anchors.topMargin: Tokens.padding.extraSmall
anchors.verticalCenter: parent.verticalCenter
color: root.isError ? Colors.palette.m3error : (root.activeFocus ? Colors.palette.m3primary : root.text ? Colors.palette.m3outline : root.placeholderTextColor)
font.family: root.font.family
font.pointSize: root.font.pointSize
font.variableAxes: root.font.variableAxes
font.weight: root.font.weight
renderType: Text.QtRendering
text: root.placeholderText
states: [
State {
name: "smallOutlined"
when: root.type === CustomTextField.Outlined && (root.activeFocus || root.text)
PropertyChanges {
placeholder.anchors.leftMargin: -(1 - root.smallFontScale) * placeholder.width / 2 + root.horizontalPadding
placeholder.scale: root.smallFontScale
}
AnchorChanges {
anchors.verticalCenter: contentWrapper.top
target: placeholder
}
},
State {
name: "smallFilled"
when: root.type === CustomTextField.Filled && (root.activeFocus || root.text)
PropertyChanges {
placeholder.anchors.leftMargin: -(1 - root.smallFontScale) * placeholder.width / 2 + root.horizontalPadding + root.leadingOffset
placeholder.scale: root.smallFontScale
}
AnchorChanges {
anchors.top: contentWrapper.top
anchors.verticalCenter: undefined
target: placeholder
}
}
]
transitions: Transition {
Anim {
properties: "scale,leftMargin"
type: Anim.DefaultEffects
}
AnchorAnim {
duration: Tokens.anim.durations.expressiveEffects
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
target: root
} }
Timer { Loader {
id: enableBlink id: leadingIconLoader
interval: 100 active: root.leadingIcon
anchors.left: parent.left
anchors.leftMargin: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter
onTriggered: cursor.disableBlink = false sourceComponent: MaterialIcon {
color: Colors.palette.m3onSurfaceVariant
text: root.leadingIcon
}
} }
Timer { Loader {
interval: 500 id: trailingIconLoader
repeat: true
running: root.activeFocus && root.cursorVisible && !cursor.disableBlink
triggeredOnStart: true
onTriggered: parent.opacity = parent.opacity === 1 ? 0 : 1 active: root.trailingIcon
} anchors.right: parent.right
anchors.rightMargin: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter
Binding { sourceComponent: MaterialIcon {
cursor.opacity: 0 color: Colors.palette.m3onSurfaceVariant
when: !root.activeFocus || !root.cursorVisible text: root.trailingIcon
}
} }
} }
Behavior on placeholderTextColor {
CAnim { Loader {
id: supportingTextLoader
active: root.effectiveSupportingText
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: root.horizontalPadding
sourceComponent: CustomText {
color: root.isError ? Colors.palette.m3error : Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
text: root.effectiveSupportingText
}
}
TapHandler {
id: tapHandler
}
Component {
id: outlineComp
Shape {
id: bg
asynchronous: true
preferredRendererType: Shape.CurveRenderer
ShapePath {
id: path
readonly property real inset: strokeWidth / 2
readonly property real outlineGap: placeholder.width * root.smallFontScale + Tokens.spacing.small * 2
property real outlineGapScale: root.activeFocus || root.text ? 1 : 0
capStyle: ShapePath.RoundCap
fillColor: "transparent"
startX: path.inset + root.horizontalPadding - root.clampedRadius + path.outlineGap * (1 - path.outlineGapScale) / 2 + path.outlineGap * path.outlineGapScale
startY: path.inset
strokeColor: root.isError ? Colors.palette.m3error : (root.activeFocus ? Colors.palette.m3primary : Colors.palette.m3outline)
strokeWidth: root.activeFocus ? 2 : 1
Behavior on outlineGapScale {
Anim {
type: Anim.DefaultEffects
}
}
Behavior on strokeColor {
CAnim {
}
}
Behavior on strokeWidth {
Anim {
}
}
PathLine {
x: bg.width - path.inset - root.clampedRadius
y: path.inset
}
PathArc {
radiusX: root.clampedRadius
radiusY: root.clampedRadius
x: bg.width - path.inset
y: path.inset + root.clampedRadius
}
PathLine {
x: bg.width - path.inset
y: bg.height - path.inset - root.clampedRadius
}
PathArc {
radiusX: root.clampedRadius
radiusY: root.clampedRadius
x: bg.width - path.inset - root.clampedRadius
y: bg.height - path.inset
}
PathLine {
x: path.inset + root.clampedRadius
y: bg.height - path.inset
}
PathArc {
radiusX: root.clampedRadius
radiusY: root.clampedRadius
x: path.inset
y: bg.height - path.inset - root.clampedRadius
}
PathLine {
x: path.inset
y: path.inset + root.clampedRadius
}
PathArc {
radiusX: root.clampedRadius
radiusY: root.clampedRadius
x: path.inset + root.clampedRadius
y: path.inset
}
PathLine {
x: path.inset + root.horizontalPadding - root.clampedRadius / 2 + path.outlineGap * (1 - path.outlineGapScale) / 2
y: path.inset
}
}
}
}
Component {
id: filledComp
CustomRect {
color: root.activeFocus ? Colors.tPalette.m3surfaceContainerHighest : Colors.tPalette.m3surfaceContainerHigh
topLeftRadius: root.clampedRadius
topRightRadius: root.clampedRadius
CustomRect {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
color: root.isError ? Colors.palette.m3error : (root.activeFocus ? Colors.palette.m3primary : Colors.palette.m3outline)
implicitHeight: root.activeFocus ? 2 : 1
Behavior on implicitHeight {
Anim {
}
}
}
} }
} }
} }
+6 -5
View File
@@ -1,15 +1,16 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import qs.Config import ZShell.Config
import qs.Services
TextInput { TextInput {
renderType: Text.NativeRendering renderType: Text.NativeRendering
selectedTextColor: DynamicColors.palette.m3onSecondaryContainer selectedTextColor: Colors.palette.m3onSecondaryContainer
selectionColor: DynamicColors.tPalette.colSecondaryContainer selectionColor: Colors.tPalette.colSecondaryContainer
font { font {
family: Appearance?.font.family.sans ?? "sans-serif" family: Config.appearance?.font.family.sans ?? "sans-serif"
hintingPreference: Font.PreferFullHinting hintingPreference: Font.PreferFullHinting
pixelSize: Appearance?.font.size.normal ?? 15 pixelSize: Config.appearance?.font.size.normal ?? 15
} }
} }
-25
View File
@@ -1,25 +0,0 @@
import QtQuick
import QtQuick.Controls
import qs.Components
ToolTip {
id: root
property bool alternativeVisibleCondition: false
property bool extraVisibleCondition: true
readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition
background: null
horizontalPadding: 10
verticalPadding: 5
visible: internalVisibleCondition
contentItem: CustomTooltipContent {
id: contentItem
horizontalPadding: root.horizontalPadding
shown: root.internalVisibleCondition
text: root.text
verticalPadding: root.verticalPadding
}
}
-54
View File
@@ -1,54 +0,0 @@
import QtQuick
import qs.Components
import qs.Config
Item {
id: root
property real horizontalPadding: 10
property bool isVisible: backgroundRectangle.implicitHeight > 0
property bool shown: false
required property string text
property real verticalPadding: 5
implicitHeight: tooltipTextObject.implicitHeight + 2 * root.verticalPadding
implicitWidth: tooltipTextObject.implicitWidth + 2 * root.horizontalPadding
Rectangle {
id: backgroundRectangle
clip: true
color: DynamicColors.tPalette.m3inverseSurface ?? "#3C4043"
implicitHeight: shown ? (tooltipTextObject.implicitHeight + 2 * root.verticalPadding) : 0
implicitWidth: shown ? (tooltipTextObject.implicitWidth + 2 * root.horizontalPadding) : 0
opacity: shown ? 1 : 0
radius: Appearance.rounding.smallest
Behavior on implicitHeight {
Anim {
}
}
Behavior on implicitWidth {
Anim {
}
}
Behavior on opacity {
Anim {
}
}
anchors {
bottom: root.bottom
horizontalCenter: root.horizontalCenter
}
CustomText {
id: tooltipTextObject
anchors.centerIn: parent
color: DynamicColors.palette.m3inverseOnSurface ?? "#FFFFFF"
text: root.text
wrapMode: Text.Wrap
}
}
}
+3 -2
View File
@@ -1,13 +1,14 @@
import QtQuick import QtQuick
import QtQuick.Effects import QtQuick.Effects
import qs.Config import ZShell.Config
import qs.Services
RectangularShadow { RectangularShadow {
property real dp: [0, 1, 3, 6, 8, 12][level] property real dp: [0, 1, 3, 6, 8, 12][level]
property int level property int level
blur: (dp * 5) ** 0.7 blur: (dp * 5) ** 0.7
color: Qt.alpha(DynamicColors.palette.m3shadow, 0.7) color: Qt.alpha(Colors.palette.m3shadow, 0.7)
offset.y: dp / 2 offset.y: dp / 2
spread: -dp * 0.3 + (dp * 0.1) ** 2 spread: -dp * 0.3 + (dp * 0.1) ** 2
-44
View File
@@ -1,44 +0,0 @@
import qs.Config
import QtQuick
CustomRect {
required property int extra
anchors.margins: 8
anchors.right: parent.right
color: DynamicColors.palette.m3tertiary
implicitHeight: count.implicitHeight + 4 * 2
implicitWidth: count.implicitWidth + 8 * 2
opacity: extra > 0 ? 1 : 0
radius: Appearance.rounding.smallest
scale: extra > 0 ? 1 : 0.5
Behavior on opacity {
Anim {
duration: MaterialEasing.expressiveEffectsTime
}
}
Behavior on scale {
Anim {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
}
}
Elevation {
anchors.fill: parent
level: 2
opacity: parent.opacity
radius: parent.radius
z: -1
}
CustomText {
id: count
anchors.centerIn: parent
animate: parent.opacity > 0
color: DynamicColors.palette.m3onTertiary
text: qsTr("+%1").arg(parent.extra)
}
}
+79
View File
@@ -0,0 +1,79 @@
import QtQuick
import Quickshell
import ZShell.Config
Image {
id: root
property int fadeInAnim: Anim.DefaultEffects
property int fadeInLargeAnim: Anim.StandardLarge
property int fadeOutAnim: Anim.FastEffects
property bool fadingOut
property bool hadPrevious
property bool preventInit
function maybeStartInAnim(): void {
if (!preventInit && !opacityInAnim.running && status === Image.Ready) {
opacityInAnim.type = hadPrevious ? fadeInAnim : fadeInLargeAnim;
opacityInAnim.start();
}
}
asynchronous: true
fillMode: Image.PreserveAspectCrop
opacity: 0
retainWhileLoading: true
sourceSize: {
const dpr = (QsWindow.window as QsWindow)?.devicePixelRatio ?? 1;
return Qt.size(width * dpr, height * dpr);
}
Anim on opacity {
id: opacityInAnim
running: false
to: 1
}
Behavior on source {
SequentialAnimation {
ScriptAction {
script: opacityInAnim.stop()
}
PropertyAction {
property: "fadingOut"
target: root
value: true
}
Anim {
property: "opacity"
target: root
to: 0
type: root.fadeOutAnim
}
PropertyAction {
property: "fadingOut"
target: root
value: false
}
PropertyAction {
property: "hadPrevious"
target: root
value: root.source
}
PropertyAction {
}
ScriptAction {
script: root.maybeStartInAnim()
}
}
}
onPreventInitChanged: maybeStartInAnim()
onStatusChanged: maybeStartInAnim()
}
+1 -1
View File
@@ -1,5 +1,5 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
BaseStyledSlider { BaseStyledSlider {
id: root id: root
+1 -1
View File
@@ -1,5 +1,5 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
BaseStyledSlider { BaseStyledSlider {
id: root id: root
-33
View File
@@ -1,33 +0,0 @@
import QtQuick
import QtQuick.Controls
import qs.Config
IconButton {
id: root
required property bool shouldBeVisible
opacity: 0
scale: 0
visible: root.scale > 0
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.small
}
}
Behavior on scale {
Anim {
}
}
onShouldBeVisibleChanged: {
if (root.shouldBeVisible) {
root.opacity = 1;
root.scale = 1;
} else {
root.opacity = 0;
root.scale = 0;
}
}
}
+9 -8
View File
@@ -1,5 +1,6 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
import qs.Services
ButtonBase { ButtonBase {
id: root id: root
@@ -7,8 +8,8 @@ ButtonBase {
property alias icon: label.text property alias icon: label.text
readonly property alias label: label readonly property alias label: label
activeColor: type === IconButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondary activeColor: type === IconButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondary
activeOnColor: type === IconButton.Filled ? DynamicColors.palette.m3onPrimary : type === IconButton.Tonal ? DynamicColors.palette.m3onSecondary : DynamicColors.palette.m3primary activeOnColor: type === IconButton.Filled ? Colors.palette.m3onPrimary : type === IconButton.Tonal ? Colors.palette.m3onSecondary : Colors.palette.m3primary
implicitHeight: { implicitHeight: {
const h = label.implicitHeight + padding * 2; const h = label.implicitHeight + padding * 2;
if (h % 2 !== 0) if (h % 2 !== 0)
@@ -18,15 +19,15 @@ ButtonBase {
implicitWidth: implicitHeight implicitWidth: implicitHeight
inactiveColor: { inactiveColor: {
if (!isToggle && type === IconButton.Filled) if (!isToggle && type === IconButton.Filled)
return DynamicColors.palette.m3primary; return Colors.palette.m3primary;
return type === IconButton.Filled ? DynamicColors.tPalette.m3surfaceContainer : DynamicColors.palette.m3secondaryContainer; return type === IconButton.Filled ? Colors.tPalette.m3surfaceContainer : Colors.palette.m3secondaryContainer;
} }
inactiveOnColor: { inactiveOnColor: {
if (!isToggle && type === IconButton.Filled) if (!isToggle && type === IconButton.Filled)
return DynamicColors.palette.m3onPrimary; return Colors.palette.m3onPrimary;
return type === IconButton.Tonal ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurfaceVariant; return type === IconButton.Tonal ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onSurfaceVariant;
} }
padding: type === IconButton.Text ? Appearance.padding.extraSmall / 2 : Appearance.padding.small padding: type === IconButton.Text ? Tokens.padding.extraSmall / 2 : Tokens.padding.small
MaterialIcon { MaterialIcon {
id: label id: label
+14 -12
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Config import ZShell.Config
import qs.Services
ButtonBase { ButtonBase {
id: root id: root
@@ -10,34 +11,34 @@ ButtonBase {
readonly property alias label: label readonly property alias label: label
property alias text: label.text property alias text: label.text
activeColor: type === TextButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondary activeColor: type === TextButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondary
activeOnColor: { activeOnColor: {
if (type === TextButton.Text) if (type === TextButton.Text)
return DynamicColors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondary; return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary;
} }
horizontalPadding: Appearance.padding.larger horizontalPadding: Tokens.padding.larger
implicitHeight: row.implicitHeight + verticalPadding * 2 implicitHeight: row.implicitHeight + verticalPadding * 2
implicitWidth: row.implicitWidth + horizontalPadding * 2 implicitWidth: row.implicitWidth + horizontalPadding * 2
inactiveColor: { inactiveColor: {
if (!isToggle && type === TextButton.Filled) if (!isToggle && type === TextButton.Filled)
return DynamicColors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? DynamicColors.tPalette.m3surfaceContainer : DynamicColors.palette.m3secondaryContainer; return type === TextButton.Filled ? Colors.tPalette.m3surfaceContainer : Colors.palette.m3secondaryContainer;
} }
inactiveOnColor: { inactiveOnColor: {
if (!isToggle && type === TextButton.Filled) if (!isToggle && type === TextButton.Filled)
return DynamicColors.palette.m3onPrimary; return Colors.palette.m3onPrimary;
if (type === TextButton.Text) if (type === TextButton.Text)
return DynamicColors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSecondaryContainer; return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer;
} }
verticalPadding: Appearance.padding.small verticalPadding: Tokens.padding.small
RowLayout { RowLayout {
id: row id: row
anchors.centerIn: parent anchors.centerIn: parent
spacing: Appearance.spacing.small spacing: Tokens.spacing.small
MaterialIcon { MaterialIcon {
id: iconLabel id: iconLabel
@@ -63,6 +64,7 @@ ButtonBase {
id: label id: label
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.topMargin: -1
color: root.onColor color: root.onColor
font: root.font font: root.font
} }
+115
View File
@@ -0,0 +1,115 @@
import QtQuick
import Quickshell
import M3Shapes
import ZShell.Config
import qs.Services
MaterialShape {
id: root
property bool animated: true
property real cRotation
property bool containsIcon
property real dampingRatio: 0.6
property real lRotation
property int morphAnimRotation: 60
property real morphScale: 0.14
property alias rotateAnimDuration: rotateAnim.duration
property int shapeIndex
property list<int> shapes: {
if (containsIcon)
return [MaterialShape.SoftBurst, MaterialShape.Cookie9Sided, MaterialShape.Pill, MaterialShape.Sunny, MaterialShape.Cookie4Sided, MaterialShape.Oval];
return [MaterialShape.SoftBurst, MaterialShape.Cookie9Sided, MaterialShape.Pentagon, MaterialShape.Pill, MaterialShape.Sunny, MaterialShape.Cookie4Sided, MaterialShape.Oval];
}
readonly property real springDuration: {
const wn = Math.sqrt(stiffness);
const r = -dampingRatio * wn;
const c = 1 / Math.sqrt(1 - dampingRatio * dampingRatio);
return Math.log(visibilityThreshold / c) / r;
}
readonly property real springMaxVelocity: {
const wn = Math.sqrt(stiffness);
const factor = Math.exp(-z * Math.acos(z) / Math.sqrt(1 - z * z));
return wn * factor;
}
property bool springSettled: true
property real stiffness: 180
property real thisLRotation
property real visibilityThreshold: 0.075
function spring(t: real): var {
const wn = Math.sqrt(stiffness);
const za = dampingRatio * wn;
const wd = wn * Math.sqrt(1 - dampingRatio * dampingRatio);
const r = za / wd;
const pos = 1 - Math.exp(-za * t) * (Math.cos(wd * t) + r * Math.sin(wd * t));
const vel = Math.exp(-za * t) * (wn * wn / wd) * Math.sin(wd * t);
return [pos, vel];
}
color: Colors.palette.m3primary
implicitSize: 38
toShape: shapes[0]
RotationAnimation on cRotation {
id: rotateAnim
duration: 4666
easing.type: Easing.Linear
from: 0
loops: Animation.Infinite
running: root.animated
to: 360
}
Behavior on color {
CAnim {
}
}
ElapsedTimer {
id: timer
}
FrameAnimation {
running: root.animated && !root.springSettled
onTriggered: {
const t = timer.elapsed();
if (t >= root.springDuration) {
root.springSettled = true;
} else {
const [pos, vel] = root.spring(t);
root.morphProgress = Math.min(1, pos); // Overshooting the morph looks weird
root.thisLRotation = pos * root.morphAnimRotation;
root.scale = 1 + vel * root.morphScale / root.springMaxVelocity;
}
}
}
Timer {
interval: 650
repeat: true
running: root.animated
triggeredOnStart: true
onTriggered: {
root.beginBatchUpdate();
root.fromShape = root.toShape;
root.shapeIndex = (root.shapeIndex + 1) % root.shapes.length;
root.toShape = root.shapes[root.shapeIndex];
root.morphProgress = 0;
root.rotation = root.rotation;
root.lRotation = (root.lRotation + root.thisLRotation) % 360;
root.thisLRotation = 0;
root.rotation = Qt.binding(() => root.cRotation + root.lRotation + root.thisLRotation);
root.springSettled = false;
timer.restart();
root.endBatchUpdate();
}
}
}
+151 -132
View File
@@ -1,12 +1,13 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
import qs.Services
Item { Item {
id: root id: root
property alias anim: marqueeAnim property alias anim: marqueeAnim
property bool animate: false property bool animate: false
property color color: DynamicColors.palette.m3onSurface property color color: Colors.palette.m3onSurface
property int fadeStrengthAnimMs: 180 property int fadeStrengthAnimMs: 180
property real fadeStrengthIdle: 0.0 property real fadeStrengthIdle: 0.0
property real fadeStrengthMoving: 1.0 property real fadeStrengthMoving: 1.0
@@ -17,13 +18,14 @@ Item {
property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle
property int leftFadeWidth: 28 property int leftFadeWidth: 28
property bool marqueeEnabled: true property bool marqueeEnabled: true
readonly property bool overflowing: metrics.width > root.width readonly property bool overflowing: metrics.width > content.width
property int pauseMs: 1200 property int pauseMs: 1200
property real pixelsPerSecond: 40 property real pixelsPerSecond: 40
property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle
property int rightFadeWidth: 28 property int rightFadeWidth: 28
property bool sliding: false property bool sliding: false
property alias text: elideText.text property alias text: elideText.text
property bool vertical: false
function durationForDistance(px): int { function durationForDistance(px): int {
return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000)); return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000));
@@ -40,8 +42,9 @@ Item {
} }
} }
clip: true clip: false
implicitHeight: elideText.implicitHeight implicitHeight: vertical ? elideText.implicitWidth : elideText.implicitHeight
implicitWidth: vertical ? elideText.implicitHeight : elideText.implicitWidth
Behavior on leftFadeStrength { Behavior on leftFadeStrength {
Anim { Anim {
@@ -52,171 +55,187 @@ Item {
} }
} }
onHeightChanged: resetMarquee()
onTextChanged: resetMarquee() onTextChanged: resetMarquee()
onVerticalChanged: resetMarquee()
onVisibleChanged: if (!visible) onVisibleChanged: if (!visible)
resetMarquee() resetMarquee()
onWidthChanged: resetMarquee() onWidthChanged: resetMarquee()
TextMetrics {
id: metrics
font: elideText.font
text: elideText.text
}
CustomText {
id: elideText
anchors.verticalCenter: parent.verticalCenter
animate: root.animate
animateProp: "scale,opacity"
color: root.color
elide: Text.ElideNone
visible: !root.overflowing
width: root.width
}
Item { Item {
id: marqueeViewport id: content
anchors.fill: parent anchors.centerIn: parent
clip: true height: root.vertical ? root.width : root.height
layer.enabled: true width: root.vertical ? root.height : root.width
visible: root.overflowing
layer.effect: OpacityMask { transform: Rotation {
maskSource: rightFadeMask angle: root.vertical ? -90 : 0
origin.x: content.width / 2
origin.y: content.height / 2
}
TextMetrics {
id: metrics
font: elideText.font
text: elideText.text
}
CustomText {
id: elideText
anchors.verticalCenter: parent.verticalCenter
animate: root.animate
animateProp: "scale,opacity"
color: root.color
elide: Text.ElideNone
visible: !root.overflowing
width: content.width
} }
Item { Item {
id: strip id: marqueeViewport
anchors.verticalCenter: parent.verticalCenter anchors.fill: parent
height: t1.implicitHeight clip: false
width: t1.width + root.gap + t2.width layer.enabled: true
x: 0 visible: root.overflowing
CustomText { layer.effect: OpacityMask {
id: t1 maskSource: rightFadeMask
animate: root.animate
animateProp: "opacity"
color: root.color
font.pointSize: elideText.font.pointSize
text: elideText.text
} }
CustomText { Item {
id: t2 id: strip
animate: root.animate anchors.verticalCenter: parent.verticalCenter
animateProp: "opacity" height: t1.implicitHeight
color: root.color width: t1.width + root.gap + t2.width
font.pointSize: elideText.font.pointSize x: 0
text: t1.text
x: t1.width + root.gap
}
}
SequentialAnimation { CustomText {
id: marqueeAnim id: t1
running: false animate: root.animate
animateProp: "opacity"
color: root.color
font.pointSize: elideText.font.pointSize
text: elideText.text
}
onFinished: pauseTimer.restart() CustomText {
id: t2
ScriptAction { animate: root.animate
script: { animateProp: "opacity"
root.sliding = true; color: root.color
root.leftFadeEnabled = true; font.pointSize: elideText.font.pointSize
text: t1.text
x: t1.width + root.gap
} }
} }
Anim { SequentialAnimation {
duration: root.durationForDistance(t1.width) id: marqueeAnim
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: 0
property: "x"
target: strip
to: -t1.width
}
ScriptAction { running: false
script: {
root.leftFadeEnabled = false; onFinished: pauseTimer.restart()
ScriptAction {
script: {
root.sliding = true;
root.leftFadeEnabled = true;
}
}
Anim {
duration: root.durationForDistance(t1.width)
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: 0
property: "x"
target: strip
to: -t1.width
}
ScriptAction {
script: {
root.leftFadeEnabled = false;
}
}
Anim {
duration: root.durationForDistance(root.gap)
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: -t1.width
property: "x"
target: strip
to: -(t1.width + root.gap)
}
ScriptAction {
script: {
root.sliding = false;
strip.x = 0;
}
} }
} }
Anim { Timer {
duration: root.durationForDistance(root.gap) id: pauseTimer
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: -t1.width
property: "x"
target: strip
to: -(t1.width + root.gap)
}
ScriptAction { interval: root.pauseMs
script: { repeat: false
root.sliding = false; running: true
strip.x = 0;
onTriggered: {
if (root.marqueeEnabled)
marqueeAnim.start();
} }
} }
} }
Timer { Rectangle {
id: pauseTimer id: rightFadeMask
interval: root.pauseMs readonly property real fadeStartPos: {
repeat: false const w = Math.max(1, width);
running: true return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w));
onTriggered: {
if (root.marqueeEnabled)
marqueeAnim.start();
} }
} readonly property real leftFadeEndPos: {
} const w = Math.max(1, width);
return Math.max(0, Math.min(1, root.leftFadeWidth / w));
Rectangle {
id: rightFadeMask
readonly property real fadeStartPos: {
const w = Math.max(1, width);
return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w));
}
readonly property real leftFadeEndPos: {
const w = Math.max(1, width);
return Math.max(0, Math.min(1, root.leftFadeWidth / w));
}
anchors.fill: marqueeViewport
layer.enabled: true
visible: false
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength)
position: 0.0
} }
GradientStop { anchors.fill: marqueeViewport
color: Qt.rgba(1, 1, 1, 1.0) layer.enabled: true
position: rightFadeMask.leftFadeEndPos visible: false
}
GradientStop { gradient: Gradient {
color: Qt.rgba(1, 1, 1, 1.0) orientation: Gradient.Horizontal
position: rightFadeMask.fadeStartPos
}
GradientStop { GradientStop {
color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength) color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength)
position: 1.0 position: 0.0
}
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0)
position: rightFadeMask.leftFadeEndPos
}
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0)
position: rightFadeMask.fadeStartPos
}
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength)
position: 1.0
}
} }
} }
} }
+4 -3
View File
@@ -1,11 +1,12 @@
import qs.Config import ZShell.Config
import qs.Services
CustomText { CustomText {
id: root id: root
readonly property list<int> allowed: [20, 24, 40, 48] readonly property list<int> allowed: [20, 24, 40, 48]
property real fill: 0 property real fill: 0
property int grade: DynamicColors.light ? 0 : -25 property int grade: Colors.light ? 0 : -25
readonly property int opsz: clampOpsz(optical) readonly property int opsz: clampOpsz(optical)
property int optical: fontInfo.pixelSize property int optical: fontInfo.pixelSize
@@ -16,7 +17,7 @@ CustomText {
} }
font.family: "Material Symbols Rounded" font.family: "Material Symbols Rounded"
font.pointSize: Appearance.font.size.larger font.pointSize: Tokens.font.size.larger
font.variableAxes: ({ font.variableAxes: ({
FILL: fill, FILL: fill,
GRAD: grade, GRAD: grade,
+22 -20
View File
@@ -3,8 +3,9 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import qs.Config import ZShell.Config
import qs.Drawers import qs.Drawers
import qs.Services
MouseArea { MouseArea {
id: root id: root
@@ -30,8 +31,9 @@ MouseArea {
signal itemSelected(item: MenuItem) signal itemSelected(item: MenuItem)
anchors.fill: parent anchors.fill: parent
cursorShape: undefined cursorShape: expanded ? Qt.ArrowCursor : undefined
enabled: expanded enabled: expanded
hoverEnabled: expanded
layer.enabled: opacity < 1 layer.enabled: opacity < 1
opacity: expanded ? 1 : 0 opacity: expanded ? 1 : 0
parent: { parent: {
@@ -76,7 +78,7 @@ MouseArea {
implicitHeight: column.implicitHeight + column.anchors.margins * 2 implicitHeight: column.implicitHeight + column.anchors.margins * 2
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2) implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2)
level: 2 level: 2
radius: Appearance.rounding.medium radius: Tokens.rounding.medium
x: { x: {
watcher.transform; watcher.transform;
const item = root.attachTo; const item = root.attachTo;
@@ -106,15 +108,15 @@ MouseArea {
CustomRect { CustomRect {
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainerLow color: Colors.palette.m3surfaceContainerLow
radius: parent.radius radius: parent.radius
ColumnLayout { ColumnLayout {
id: column id: column
anchors.fill: parent anchors.fill: parent
anchors.margins: Appearance.padding.extraSmall anchors.margins: Tokens.padding.extraSmall
spacing: Appearance.spacing.extraSmall spacing: Tokens.spacing.extraSmall
Repeater { Repeater {
id: repeater id: repeater
@@ -124,15 +126,15 @@ MouseArea {
CustomRect { CustomRect {
id: item id: item
readonly property bool active: modelData === root.active readonly property bool active: modelData === root?.active
required property int index required property int index
required property MenuItem modelData required property MenuItem modelData
Layout.fillWidth: true Layout.fillWidth: true
color: Qt.alpha(DynamicColors.palette.m3tertiaryContainer, active ? 1 : 0) color: Qt.alpha(Colors.palette.m3tertiaryContainer, active ? 1 : 0)
implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.larger * 2 implicitHeight: menuOptionRow.implicitHeight + Tokens.padding.larger * 2
implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.larger * 2 implicitWidth: menuOptionRow.implicitWidth + Tokens.padding.larger * 2
radius: Appearance.rounding.small radius: Tokens.rounding.small
Behavior on radius { Behavior on radius {
Anim { Anim {
@@ -140,7 +142,7 @@ MouseArea {
} }
StateLayer { StateLayer {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurface
enabled: root.expanded enabled: root.expanded
onClicked: { onClicked: {
@@ -155,30 +157,30 @@ MouseArea {
id: menuOptionRow id: menuOptionRow
anchors.fill: parent anchors.fill: parent
anchors.margins: Appearance.padding.larger anchors.margins: Tokens.padding.larger
spacing: Appearance.spacing.small spacing: Tokens.spacing.small
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurfaceVariant
text: item.modelData.icon text: item.modelData?.icon ?? ""
} }
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurface
text: item.modelData.text text: item.modelData?.text ?? ""
} }
Loader { Loader {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
active: item.modelData.trailingIcon.length > 0 active: item.modelData?.trailingIcon.length > 0
asynchronous: true asynchronous: true
visible: active visible: active
sourceComponent: MaterialIcon { sourceComponent: MaterialIcon {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurfaceVariant
text: item.modelData.trailingIcon text: item.modelData.trailingIcon
} }
} }
-76
View File
@@ -1,76 +0,0 @@
import QtQuick
Path {
id: root
required property real viewHeight
required property real viewWidth
startX: root.viewWidth / 2
startY: 0
PathAttribute {
name: "itemOpacity"
value: 0.25
}
PathLine {
x: root.viewWidth / 2
y: root.viewHeight * (1 / 6)
}
PathAttribute {
name: "itemOpacity"
value: 0.45
}
PathLine {
x: root.viewWidth / 2
y: root.viewHeight * (2 / 6)
}
PathAttribute {
name: "itemOpacity"
value: 0.70
}
PathLine {
x: root.viewWidth / 2
y: root.viewHeight * (3 / 6)
}
PathAttribute {
name: "itemOpacity"
value: 1.00
}
PathLine {
x: root.viewWidth / 2
y: root.viewHeight * (4 / 6)
}
PathAttribute {
name: "itemOpacity"
value: 0.70
}
PathLine {
x: root.viewWidth / 2
y: root.viewHeight * (5 / 6)
}
PathAttribute {
name: "itemOpacity"
value: 0.45
}
PathLine {
x: root.viewWidth / 2
y: root.viewHeight
}
PathAttribute {
name: "itemOpacity"
value: 0.25
}
}
-180
View File
@@ -1,180 +0,0 @@
import QtQuick
import QtQuick.Effects
import qs.Config
Elevation {
id: root
required property int currentIndex
property bool expanded
required property int from
property color insideTextColor: DynamicColors.palette.m3onPrimary
property int itemHeight
property int listHeight: 200
property color outsideTextColor: DynamicColors.palette.m3onSurfaceVariant
readonly property var spinnerModel: root.range(root.from, root.to)
required property int to
property Item triggerItem
signal itemSelected(item: int)
function range(first, last) {
let out = [];
for (let i = first; i <= last; ++i)
out.push(i);
return out;
}
implicitHeight: root.expanded ? view.implicitHeight : 0
level: root.expanded ? 2 : 0
radius: itemHeight / 2
visible: implicitHeight > 0
z: root.expanded ? 100 : 0
Behavior on implicitHeight {
Anim {
}
}
onExpandedChanged: {
if (!root.expanded)
root.itemSelected(view.currentIndex + 1);
}
Component {
id: spinnerDelegate
Item {
id: wrapper
readonly property color delegateTextColor: wrapper.PathView.view ? wrapper.PathView.view.delegateTextColor : "white"
required property var modelData
height: root.itemHeight
opacity: wrapper.PathView.itemOpacity
visible: wrapper.PathView.onPath
width: wrapper.PathView.view ? wrapper.PathView.view.width : 0
z: wrapper.PathView.isCurrentItem ? 100 : Math.round(wrapper.PathView.itemScale * 100)
CustomText {
anchors.centerIn: parent
color: wrapper.delegateTextColor
font.pointSize: Appearance.font.size.large
text: wrapper.modelData
}
}
}
CustomClippingRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainer
radius: parent.radius
z: root.z
// Main visible spinner: normal/outside text color
PathView {
id: view
property color delegateTextColor: root.outsideTextColor
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
currentIndex: root.currentIndex - 1
delegate: spinnerDelegate
dragMargin: width
highlightRangeMode: PathView.StrictlyEnforceRange
implicitHeight: root.listHeight
model: root.spinnerModel
pathItemCount: 7
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
snapMode: PathView.SnapToItem
path: PathMenu {
viewHeight: view.height
viewWidth: view.width
}
}
// The selection rectangle itself
CustomRect {
id: selectionRect
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3primary
height: root.itemHeight
radius: root.itemHeight / 2
width: parent.width
z: 2
}
// Hidden source: same PathView, but with the "inside selection" text color
Item {
id: selectedTextSource
anchors.fill: parent
layer.enabled: true
visible: false
PathView {
id: selectedTextView
property color delegateTextColor: root.insideTextColor
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
currentIndex: view.currentIndex
delegate: spinnerDelegate
dragMargin: view.dragMargin
highlightRangeMode: view.highlightRangeMode
implicitHeight: root.listHeight
interactive: false
model: view.model
// Keep this PathView visually locked to the real one
offset: view.offset
pathItemCount: view.pathItemCount
preferredHighlightBegin: view.preferredHighlightBegin
preferredHighlightEnd: view.preferredHighlightEnd
snapMode: view.snapMode
path: PathMenu {
viewHeight: selectedTextView.height
viewWidth: selectedTextView.width
}
}
}
// Mask matching the selection rectangle
Item {
id: selectionMask
anchors.fill: parent
layer.enabled: true
visible: false
CustomRect {
color: "white"
height: selectionRect.height
radius: selectionRect.radius
width: selectionRect.width
x: selectionRect.x
y: selectionRect.y
}
}
// Only show the "inside selection" text where the mask exists
MultiEffect {
anchors.fill: selectedTextSource
maskEnabled: true
maskInverted: false
maskSource: selectionMask
source: selectedTextSource
z: 3
}
}
}
+95
View File
@@ -0,0 +1,95 @@
import QtQuick
import ZShell.Config
import qs.Services
TextFieldBase {
id: root
readonly property alias bg: bg
readonly property alias clearIcon: clearIcon
readonly property alias searchIcon: searchIcon
bottomPadding: Tokens.padding.large
leftPadding: searchIcon.width + searchIcon.anchors.leftMargin + Tokens.spacing.small
rightPadding: clearIcon.width + clearIcon.anchors.rightMargin + Tokens.spacing.small
topPadding: Tokens.padding.large
background: CustomRect {
id: bg
anchors.fill: parent
color: Colors.tPalette.m3surfaceContainer
radius: Tokens.rounding.full
StateLayer {
id: stateLayer
cursorShape: Qt.IBeamCursor
enabled: !root.activeFocus
manualPressOverride: tapHandler.pressed
onClicked: root.focus = true
}
}
onPressed: {
if (stateLayer.enabled)
stateLayer.press(stateLayer.mouseX, stateLayer.mouseY);
}
CustomText {
id: placeholder
anchors.left: parent.left
anchors.leftMargin: root.leftPadding
anchors.verticalCenter: parent.verticalCenter
color: root.placeholderTextColor
font: root.font
opacity: root.text ? 0 : 1
text: root.placeholderText
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
MaterialIcon {
id: searchIcon
anchors.left: parent.left
anchors.leftMargin: Tokens.padding.large
anchors.verticalCenter: parent.verticalCenter
color: Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.large
text: "search"
}
IconButton {
id: clearIcon
anchors.right: parent.right
anchors.rightMargin: Tokens.padding.larger
anchors.verticalCenter: parent.verticalCenter
enabled: root.text
icon: "clear"
opacity: root.text ? 1 : 0
radius: Tokens.rounding.full
radiusMorph: false
stateLayer.hoverEnabled: enabled
type: IconButton.Text
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
onClicked: root.clear()
}
TapHandler {
id: tapHandler
}
}
-50
View File
@@ -1,50 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Config
CustomRect {
id: root
required property string label
required property real max
required property real min
property var onValueModified: function (value) {}
property real step: 1
required property real value
Layout.fillWidth: true
color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, 2)
implicitHeight: row.implicitHeight + Appearance.padding.large * 2
radius: Appearance.rounding.normal
Behavior on implicitHeight {
Anim {
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.large
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.normal
CustomText {
Layout.fillWidth: true
text: root.label
}
CustomSpinBox {
max: root.max
min: root.min
step: root.step
value: root.value
onValueModified: value => {
root.onValueModified(value);
}
}
}
}
+8 -6
View File
@@ -3,7 +3,8 @@ import QtQuick.Shapes
import ZShell import ZShell
import ZShell.Components import ZShell.Components
import qs.Helpers import qs.Helpers
import qs.Config import ZShell.Config
import qs.Services
MouseArea { MouseArea {
id: root id: root
@@ -20,6 +21,7 @@ MouseArea {
return (Math.sqrt(Math.max(d1, d2, d3, d4)) + (shapeMorph ? 24 : 0)) * 1.3; return (Math.sqrt(Math.max(d1, d2, d3, d4)) + (shapeMorph ? 24 : 0)) * 1.3;
} }
property real endRadiusAtPress property real endRadiusAtPress
property bool manualHoverOverride
property bool manualPressOverride property bool manualPressOverride
property real pressX: width / 2 property real pressX: width / 2
property real pressY: height / 2 property real pressY: height / 2
@@ -27,7 +29,7 @@ MouseArea {
readonly property alias rect: base readonly property alias rect: base
property bool shapeMorph property bool shapeMorph
property bool showHoverBackground: true property bool showHoverBackground: true
property real stateOpacity: containsMouse ? 0.08 : 0 property real stateOpacity: containsMouse || manualHoverOverride ? 0.08 : 0
property alias topLeftRadius: base.topLeftRadius property alias topLeftRadius: base.topLeftRadius
property alias topRightRadius: base.topRightRadius property alias topRightRadius: base.topRightRadius
@@ -51,7 +53,7 @@ MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: !enabled ? undefined : Qt.PointingHandCursor cursorShape: !enabled ? undefined : Qt.PointingHandCursor
enabled: parent.enabled && !Visibilities.getForActive().isDrawing enabled: parent.enabled && !Visibilities.getForActive()?.isDrawing
hoverEnabled: true hoverEnabled: true
Behavior on stateOpacity { Behavior on stateOpacity {
@@ -78,8 +80,8 @@ MouseArea {
id: rippleAnim id: rippleAnim
alwaysRunToEnd: true alwaysRunToEnd: true
duration: Appearance.anim.durations.expressiveSlowEffects * 2 duration: Tokens.anim.durations.expressiveSlowEffects * 2
easing.bezierCurve: Appearance.anim.curves.standard easing.bezierCurve: Tokens.anim.curves.standard
property: "circleRadius" property: "circleRadius"
target: root target: root
to: root.endRadius to: root.endRadius
@@ -100,7 +102,7 @@ MouseArea {
anchors.fill: parent anchors.fill: parent
bottomLeftRadius: root.parent?.bottomLeftRadius ?? radius ?? 0 bottomLeftRadius: root.parent?.bottomLeftRadius ?? radius ?? 0
bottomRightRadius: root.parent?.bottomRightRadius ?? radius ?? 0 bottomRightRadius: root.parent?.bottomRightRadius ?? radius ?? 0
color: DynamicColors.palette.m3onSurface color: Colors.palette.m3onSurface
opacity: root.stateOpacity opacity: root.stateOpacity
// Pick up radius from parent if it has one (parent can be anything with radius props) // Pick up radius from parent if it has one (parent can be anything with radius props)
// qmllint disable missing-property // qmllint disable missing-property
+12 -11
View File
@@ -1,5 +1,6 @@
import QtQuick import QtQuick
import qs.Config import ZShell.Config
import qs.Services
ButtonBase { ButtonBase {
id: root id: root
@@ -7,28 +8,28 @@ ButtonBase {
readonly property alias label: label readonly property alias label: label
property alias text: label.text property alias text: label.text
activeColor: type === TextButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondary activeColor: type === TextButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondary
activeOnColor: { activeOnColor: {
if (type === TextButton.Text) if (type === TextButton.Text)
return DynamicColors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondary; return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary;
} }
horizontalPadding: Appearance.padding.normal horizontalPadding: Tokens.padding.normal
implicitHeight: label.implicitHeight + verticalPadding * 2 implicitHeight: label.implicitHeight + verticalPadding * 2
implicitWidth: label.implicitWidth + horizontalPadding * 2 implicitWidth: label.implicitWidth + horizontalPadding * 2
inactiveColor: { inactiveColor: {
if (!isToggle && type === TextButton.Filled) if (!isToggle && type === TextButton.Filled)
return DynamicColors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? DynamicColors.tPalette.m3surfaceContainer : DynamicColors.palette.m3secondaryContainer; return type === TextButton.Filled ? Colors.tPalette.m3surfaceContainer : Colors.palette.m3secondaryContainer;
} }
inactiveOnColor: { inactiveOnColor: {
if (!isToggle && type === TextButton.Filled) if (!isToggle && type === TextButton.Filled)
return DynamicColors.palette.m3onPrimary; return Colors.palette.m3onPrimary;
if (type === TextButton.Text) if (type === TextButton.Text)
return DynamicColors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSecondaryContainer; return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer;
} }
verticalPadding: Appearance.padding.small verticalPadding: Tokens.padding.small
CustomText { CustomText {
id: label id: label
+89
View File
@@ -0,0 +1,89 @@
import QtQuick
import QtQuick.Templates
import ZShell.Config
import qs.Services
TextField {
id: root
color: Colors.palette.m3onSurface
cursorVisible: !readOnly
font.pointSize: Tokens.font.size.small
implicitHeight: contentHeight + topPadding + bottomPadding
implicitWidth: contentWidth + leftPadding + rightPadding
placeholderTextColor: Colors.palette.m3onSurfaceVariant // No anim cause placeholder is custom
renderType: echoMode === TextField.Password ? TextField.QtRendering : TextField.NativeRendering
selectedTextColor: color
selectionColor: Qt.alpha(Colors.palette.m3primary, 0.4)
verticalAlignment: TextInput.AlignVCenter
Behavior on color {
CAnim {
}
}
cursorDelegate: Item {
}
Behavior on selectionColor {
CAnim {
}
}
CustomRect {
id: cursor
property bool disableBlink
color: Colors.palette.m3primary
implicitHeight: root.cursorRectangle.height
implicitWidth: 1.5
radius: Tokens.rounding.large
x: root.cursorRectangle.x
y: root.cursorRectangle.y
Behavior on opacity {
Anim {
type: Anim.StandardSmall
}
}
Behavior on x {
Anim {
duration: Tokens.anim.durations.expressiveFastEffects
easing.bezierCurve: [0.2, 1, 0.21, 1, 1, 1]
}
}
Connections {
function onCursorPositionChanged(): void {
if (root.activeFocus && root.cursorVisible) {
cursor.opacity = 1;
cursor.disableBlink = true;
enableBlink.restart();
}
}
target: root
}
Timer {
id: enableBlink
interval: 500
onTriggered: cursor.disableBlink = false
}
Timer {
interval: 500
repeat: true
running: root.activeFocus && root.cursorVisible && !cursor.disableBlink
triggeredOnStart: true
onTriggered: parent.opacity = parent.opacity === 1 ? 0 : 1
}
Binding {
cursor.opacity: 0
when: !root.activeFocus || !root.cursorVisible
}
}
}
+36 -35
View File
@@ -2,7 +2,8 @@ import ZShell
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import ZShell.Config
import qs.Services
CustomRect { CustomRect {
id: root id: root
@@ -12,27 +13,27 @@ CustomRect {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
border.color: { border.color: {
let colour = DynamicColors.palette.m3outlineVariant; let colour = Colors.palette.m3outlineVariant;
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
colour = DynamicColors.palette.m3success; colour = Colors.palette.m3success;
if (root.modelData.type === Toast.Warning) if (root.modelData.type === Toast.Warning)
colour = DynamicColors.palette.m3secondaryContainer; colour = Colors.palette.m3secondaryContainer;
if (root.modelData.type === Toast.Error) if (root.modelData.type === Toast.Error)
colour = DynamicColors.palette.m3error; colour = Colors.palette.m3error;
return Qt.alpha(colour, 0.3); return Qt.alpha(colour, 0.3);
} }
border.width: 1 border.width: 1
color: { color: {
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3successContainer; return Colors.palette.m3successContainer;
if (root.modelData.type === Toast.Warning) if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3secondary; return Colors.palette.m3secondary;
if (root.modelData.type === Toast.Error) if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3errorContainer; return Colors.palette.m3errorContainer;
return DynamicColors.palette.m3surface; return Colors.palette.m3surface;
} }
implicitHeight: layout.implicitHeight + Appearance.padding.smaller * 2 implicitHeight: layout.implicitHeight + Tokens.padding.smaller * 2
radius: Appearance.rounding.normal radius: Tokens.rounding.normal
Behavior on border.color { Behavior on border.color {
CAnim { CAnim {
@@ -51,24 +52,24 @@ CustomRect {
id: layout id: layout
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal anchors.leftMargin: Tokens.padding.normal
anchors.margins: Appearance.padding.smaller anchors.margins: Tokens.padding.smaller
anchors.rightMargin: Appearance.padding.normal anchors.rightMargin: Tokens.padding.normal
spacing: Appearance.spacing.normal spacing: Tokens.spacing.normal
CustomRect { CustomRect {
color: { color: {
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3success; return Colors.palette.m3success;
if (root.modelData.type === Toast.Warning) if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3secondaryContainer; return Colors.palette.m3secondaryContainer;
if (root.modelData.type === Toast.Error) if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3error; return Colors.palette.m3error;
return DynamicColors.palette.m3surfaceContainerHigh; return Colors.palette.m3surfaceContainerHigh;
} }
implicitHeight: icon.implicitHeight + Appearance.padding.smaller * 2 implicitHeight: icon.implicitHeight + Tokens.padding.smaller * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: Appearance.rounding.normal radius: Tokens.rounding.normal
MaterialIcon { MaterialIcon {
id: icon id: icon
@@ -76,14 +77,14 @@ CustomRect {
anchors.centerIn: parent anchors.centerIn: parent
color: { color: {
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3onSuccess; return Colors.palette.m3onSuccess;
if (root.modelData.type === Toast.Warning) if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3onSecondaryContainer; return Colors.palette.m3onSecondaryContainer;
if (root.modelData.type === Toast.Error) if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3onError; return Colors.palette.m3onError;
return DynamicColors.palette.m3onSurfaceVariant; return Colors.palette.m3onSurfaceVariant;
} }
font.pointSize: Math.round(Appearance.font.size.large * 1.2) font.pointSize: Math.round(Tokens.font.size.large * 1.2)
text: root.modelData.icon text: root.modelData.icon
} }
} }
@@ -98,15 +99,15 @@ CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
color: { color: {
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3onSuccessContainer; return Colors.palette.m3onSuccessContainer;
if (root.modelData.type === Toast.Warning) if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3onSecondary; return Colors.palette.m3onSecondary;
if (root.modelData.type === Toast.Error) if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3onErrorContainer; return Colors.palette.m3onErrorContainer;
return DynamicColors.palette.m3onSurface; return Colors.palette.m3onSurface;
} }
elide: Text.ElideRight elide: Text.ElideRight
font.pointSize: Appearance.font.size.normal font.pointSize: Tokens.font.size.normal
text: root.modelData.title text: root.modelData.title
} }
@@ -114,12 +115,12 @@ CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
color: { color: {
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3onSuccessContainer; return Colors.palette.m3onSuccessContainer;
if (root.modelData.type === Toast.Warning) if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3onSecondary; return Colors.palette.m3onSecondary;
if (root.modelData.type === Toast.Error) if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3onErrorContainer; return Colors.palette.m3onErrorContainer;
return DynamicColors.palette.m3onSurface; return Colors.palette.m3onSurface;
} }
elide: Text.ElideRight elide: Text.ElideRight
opacity: 0.8 opacity: 0.8
+7 -7
View File
@@ -4,13 +4,13 @@ import ZShell
import Quickshell import Quickshell
import QtQuick import QtQuick
import qs.Components import qs.Components
import qs.Config import ZShell.Config
Item { Item {
id: root id: root
property bool flag property bool flag
readonly property int spacing: Appearance.spacing.small readonly property int spacing: Tokens.spacing.small
implicitHeight: { implicitHeight: {
let h = -spacing; let h = -spacing;
@@ -21,7 +21,7 @@ Item {
} }
return h; return h;
} }
implicitWidth: Config.utilities.sizes.toastWidth - Appearance.padding.normal * 2 implicitWidth: Config.utilities.sizes.toastWidth - Tokens.padding.normal * 2
Repeater { Repeater {
id: repeater id: repeater
@@ -81,8 +81,8 @@ Item {
Behavior on anchors.bottomMargin { Behavior on anchors.bottomMargin {
Anim { Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -104,8 +104,8 @@ Item {
Anim { Anim {
id: initAnim id: initAnim
duration: Appearance.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
from: 0 from: 0
properties: "opacity,scale" properties: "opacity,scale"
target: toast target: toast
+71
View File
@@ -0,0 +1,71 @@
pragma ComponentBehavior: Bound
import QtQuick
import qs.Effects
CustomFlickable {
id: root
property real bottomFadeOpacity: fadeShouldBeActive(false) ? 0 : 1
property real fadeAmount: 0.1
property real topFadeOpacity: fadeShouldBeActive(true) ? 0 : 1
function fadeShouldBeActive(isStart: bool): bool {
// When content is smaller than flickable size, hide fade when rebound starts
if (contentHeight + topMargin + bottomMargin < height && rebound.running && ((isStart ? verticalOvershoot > 0 : verticalOvershoot < 0)))
return false;
if (isStart)
return visibleArea.yPosition > 0;
return visibleArea.yPosition + visibleArea.heightRatio < 1;
}
flickableDirection: Flickable.VerticalFlick
layer.enabled: true
Behavior on bottomFadeOpacity {
Anim {
type: Anim.SlowEffects
}
}
layer.effect: Mask {
maskSource: mask
Rectangle {
id: mask
anchors.fill: parent
layer.enabled: true
visible: false
gradient: Gradient {
orientation: Gradient.Vertical
GradientStop {
color: Qt.rgba(0, 0, 0, root.topFadeOpacity)
position: 0
}
GradientStop {
color: Qt.rgba(0, 0, 0, 1)
position: root.fadeAmount
}
GradientStop {
color: Qt.rgba(0, 0, 0, 1)
position: 1 - root.fadeAmount
}
GradientStop {
color: Qt.rgba(0, 0, 0, root.bottomFadeOpacity)
position: 1
}
}
}
}
Behavior on topFadeOpacity {
Anim {
type: Anim.SlowEffects
}
}
}
+102
View File
@@ -0,0 +1,102 @@
pragma ComponentBehavior: Bound
import QtQuick
import qs.Effects
CustomListView {
id: root
property real endFadeOpacity: fadeShouldBeActive(false) ? 0 : 1
property real fadeAmount: 0.1
readonly property bool horizontal: orientation === ListView.Horizontal
property real startFadeOpacity: fadeShouldBeActive(true) ? 0 : 1
function contentSize(): real {
return horizontal ? contentWidth : contentHeight;
}
function fadeShouldBeActive(isStart: bool): bool {
// When content is smaller than flickable size, hide fade when rebound starts.
if (contentSize() + marginStart() + marginEnd() < viewportSize() && rebound.running && ((isStart ? overshootStart() > 0 : overshootStart() < 0))) {
return false;
}
if (isStart)
return visibleStart() > 0;
return visibleStart() + visibleRatio() < 1;
}
function marginEnd(): real {
return horizontal ? rightMargin : bottomMargin;
}
function marginStart(): real {
return horizontal ? leftMargin : topMargin;
}
function overshootStart(): real {
return horizontal ? horizontalOvershoot : verticalOvershoot;
}
function viewportSize(): real {
return horizontal ? width : height;
}
function visibleRatio(): real {
return horizontal ? visibleArea.widthRatio : visibleArea.heightRatio;
}
function visibleStart(): real {
return horizontal ? visibleArea.xPosition : visibleArea.yPosition;
}
flickableDirection: horizontal ? Flickable.HorizontalFlick : Flickable.VerticalFlick
layer.enabled: true
Behavior on endFadeOpacity {
Anim {
type: Anim.SlowEffects
}
}
layer.effect: Mask {
maskSource: mask
Rectangle {
id: mask
anchors.fill: parent
layer.enabled: true
visible: false
gradient: Gradient {
orientation: root.horizontal ? Gradient.Horizontal : Gradient.Vertical
GradientStop {
color: Qt.rgba(0, 0, 0, root.startFadeOpacity)
position: 0
}
GradientStop {
color: Qt.rgba(0, 0, 0, 1)
position: root.fadeAmount
}
GradientStop {
color: Qt.rgba(0, 0, 0, 1)
position: 1 - root.fadeAmount
}
GradientStop {
color: Qt.rgba(0, 0, 0, root.endFadeOpacity)
position: 1
}
}
}
}
Behavior on startFadeOpacity {
Anim {
type: Anim.SlowEffects
}
}
}
+47
View File
@@ -0,0 +1,47 @@
import QtQuick
import QtQuick.Shapes
import ZShell.Config
import qs.Services
Shape {
id: root
property real amplitude: 3
property color color: Colors.palette.m3surfaceContainer
readonly property real waveHeight: amplitude * 2
property int waves: 4
asynchronous: true
preferredRendererType: Shape.CurveRenderer
ShapePath {
fillColor: root.color
strokeColor: "transparent"
strokeWidth: 0
Behavior on fillColor {
CAnim {
}
}
PathSvg {
path: {
const w = root.width;
const h = root.height;
const a = root.amplitude;
const n = Math.max(1, root.waves);
const wl = w / n;
const half = wl / 2;
let d = `M 0,${a} `;
for (let i = 0; i < n; ++i) {
const x = i * wl;
d += `Q ${x + half / 2},${-a} ${x + half},${a} `;
d += `Q ${x + half + half / 2},${3 * a} ${x + wl},${a} `;
}
d += `L ${w},${h} L 0,${h} Z`;
return d;
}
}
}
}
-13
View File
@@ -1,13 +0,0 @@
import Quickshell.Io
JsonObject {
property Accents accents: Accents {
}
component Accents: JsonObject {
property string primary: "#4080ff"
property string primaryAlt: "#60a0ff"
property string warning: "#ff6b6b"
property string warningAlt: "#ff8787"
}
}
-13
View File
@@ -1,13 +0,0 @@
pragma Singleton
import Quickshell
Singleton {
readonly property AppearanceConf.Anim anim: Config.appearance.anim
readonly property AppearanceConf.Deform deform: Config.appearance.deform
readonly property AppearanceConf.FontStuff font: Config.appearance.font
readonly property AppearanceConf.Padding padding: Config.appearance.padding
readonly property AppearanceConf.Rounding rounding: Config.appearance.rounding
readonly property AppearanceConf.Spacing spacing: Config.appearance.spacing
readonly property AppearanceConf.Transparency transparency: Config.appearance.transparency
}
-116
View File
@@ -1,116 +0,0 @@
import Quickshell.Io
JsonObject {
property Anim anim: Anim {
}
property Deform deform: Deform {
}
property FontStuff font: FontStuff {
}
property Padding padding: Padding {
}
property Rounding rounding: Rounding {
}
property Spacing spacing: Spacing {
}
property Transparency transparency: Transparency {
}
component Anim: JsonObject {
property AnimCurves curves: AnimCurves {
}
property AnimDurations durations: AnimDurations {
}
property real mediaGifSpeedAdjustment: 300
property real sessionGifSpeed: 0.7
}
component AnimCurves: JsonObject {
property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
property list<real> expressiveDefaultEffects: [0.34, 0.8, 0.34, 1, 1, 1]
property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1]
property list<real> expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1]
property list<real> expressiveFastEffects: [0.31, 0.94, 0.34, 1, 1, 1]
property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]
property list<real> expressiveSlowEffects: [0.34, 0.88, 0.34, 1, 1, 1]
property list<real> expressiveSlowSpatial: [0.39, 1.29, 0.35, 0.98, 1, 1]
property list<real> standard: [0.2, 0, 0, 1, 1, 1]
property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
}
component AnimDurations: JsonObject {
property int expressiveDefaultSpatial: 500 * scale
property int expressiveEffects: 200 * scale
property int expressiveFastEffects: 150 * scale
property int expressiveFastSpatial: 350 * scale
property int expressiveSlowEffects: 300 * scale
property int extraLarge: 1000 * scale
property int large: 600 * scale
property int normal: 400 * scale
property real scale: 1
property int small: 200 * scale
}
component Deform: JsonObject {
property real scale: 1
}
component FontFamily: JsonObject {
property string clock: "Rubik"
property string material: "Material Symbols Rounded"
property string mono: "CaskaydiaCove NF"
property string sans: "Segoe UI Variable Text"
}
component FontSize: JsonObject {
property int extraLarge: 28 * scale
property int large: 18 * scale
property int larger: 16 * scale
property int medium: 14 * scale
property int normal: 13 * scale
property real scale: 1
property int small: 11 * scale
property int smaller: 12 * scale
}
component FontStuff: JsonObject {
property FontFamily family: FontFamily {
}
property FontSize size: FontSize {
}
}
component Padding: JsonObject {
property int extraLarge: 28 * scale
property int extraLargeIncreased: 32 * scale
property int extraSmall: 4 * scale
property int large: 16 * scale
property int largeIncreased: 20 * scale
property int larger: 12 * scale
property int normal: 8 * scale
property real scale: 1
property int small: 5 * scale
property int smaller: 7 * scale
property int smallest: 2 * scale
}
component Rounding: JsonObject {
property int extraSmall: 4 * scale
property int full: 1000 * scale
property int large: 24 * scale
property int medium: 16 * scale
property int normal: 18 * scale
property real scale: 1
property int small: 12 * scale
property int smallest: 8 * scale
}
component Spacing: JsonObject {
property int extraSmall: 4 * scale
property int large: 20 * scale
property int larger: 16 * scale
property int normal: 12 * scale
property real scale: 1
property int small: 8 * scale
property int smaller: 10 * scale
}
component Transparency: JsonObject {
property real base: 0.85
property bool enabled: false
property real layers: 0.4
}
}
-14
View File
@@ -1,14 +0,0 @@
import Quickshell.Io
import qs.Config
JsonObject {
property bool enabled: true
property int wallFadeDuration: MaterialEasing.standardTime
property real alignX: 0.5
property real alignY: 0.5
property real zoom: 1.0
property real sourceClipX: 0
property real sourceClipY: 0
property real sourceClipW: 0
property real sourceClipH: 0
}
-77
View File
@@ -1,77 +0,0 @@
import Quickshell.Io
JsonObject {
property bool autoHide: false
property int border: 8
property list<var> entries: [
{
id: "workspaces",
enabled: true
},
{
id: "media",
enabled: true
},
{
id: "resources",
enabled: true
},
{
id: "updates",
enabled: true
},
{
id: "spacer",
enabled: true
},
{
id: "activeWindow",
enabled: true
},
{
id: "spacer",
enabled: true
},
{
id: "hyprsunset",
enabled: true
},
{
id: "tray",
enabled: true
},
{
id: "network",
enabled: false
},
{
id: "clock",
enabled: true
},
{
id: "notifBell",
enabled: true
},
]
property int height: 34
property bool hideWhenNotif: false
property Popouts popouts: Popouts {
}
property int rounding: 8
property int smoothing: 32
property Tray tray: Tray {
}
component Popouts: JsonObject {
property bool activeWindow: true
property bool audio: true
property bool clock: true
property bool network: true
property bool resources: true
property bool tray: true
property bool upower: true
}
component Tray: JsonObject {
property int trayIconSize: 24
}
}
-15
View File
@@ -1,15 +0,0 @@
import Quickshell.Io
JsonObject {
property bool enabled: true
property int maxEntriesShown: 10
property Sizes sizes: Sizes {
}
component Sizes: JsonObject {
property int itemHeight: 60
property int minPreviewWidth: 200
property int previewWidth: 500
property int width: 500
}
}
-13
View File
@@ -1,13 +0,0 @@
import Quickshell.Io
JsonObject {
property Presets presets: Presets {
}
property string schemeType: "vibrant"
component Presets: JsonObject {
property string accent: ""
property string name: ""
property string variant: ""
}
}
-497
View File
@@ -1,497 +0,0 @@
pragma Singleton
import Quickshell
import Quickshell.Io
import ZShell
import QtQuick
import qs.Helpers
import qs.Paths
Singleton {
id: root
property alias appearance: adapter.appearance
property alias background: adapter.background
property alias barConfig: adapter.barConfig
property alias clipboard: adapter.clipboard
property alias colors: adapter.colors
property alias dashboard: adapter.dashboard
property alias dock: adapter.dock
property alias general: adapter.general
property alias launcher: adapter.launcher
property alias lock: adapter.lock
property alias notifs: adapter.notifs
property alias osd: adapter.osd
property alias overview: adapter.overview
property bool recentlySaved: false
property alias screenshot: adapter.screenshot
property alias services: adapter.services
property alias sidebar: adapter.sidebar
property alias utilities: adapter.utilities
function save(): void {
saveTimer.restart();
recentlySaved = true;
recentSaveCooldown.restart();
}
function saveNoToast(): void {
saveTimer.restart();
}
function serializeAppearance(): var {
return {
rounding: {
scale: appearance.rounding.scale
},
spacing: {
scale: appearance.spacing.scale
},
padding: {
scale: appearance.padding.scale
},
deform: {
scale: appearance.deform.scale
},
font: {
family: {
sans: appearance.font.family.sans,
mono: appearance.font.family.mono,
material: appearance.font.family.material,
clock: appearance.font.family.clock
},
size: {
scale: appearance.font.size.scale
}
},
anim: {
mediaGifSpeedAdjustment: appearance.anim.mediaGifSpeedAdjustment,
sessionGifSpeed: appearance.anim.sessionGifSpeed,
durations: {
scale: appearance.anim.durations.scale
}
},
transparency: {
enabled: appearance.transparency.enabled,
base: appearance.transparency.base,
layers: appearance.transparency.layers
}
};
}
function serializeBackground(): var {
return {
wallFadeDuration: background.wallFadeDuration,
enabled: background.enabled,
alignX: background.alignX,
sourceClipX: background.sourceClipX,
sourceClipY: background.sourceClipY,
sourceClipW: background.sourceClipW,
sourceClipH: background.sourceClipH,
alignY: background.alignY,
zoom: background.zoom
};
}
function serializeBar(): var {
return {
autoHide: barConfig.autoHide,
hideWhenNotif: barConfig.hideWhenNotif,
rounding: barConfig.rounding,
border: barConfig.border,
smoothing: barConfig.smoothing,
height: barConfig.height,
tray: {
trayIconSize: barConfig.tray.trayIconSize
},
popouts: {
tray: barConfig.popouts.tray,
audio: barConfig.popouts.audio,
activeWindow: barConfig.popouts.activeWindow,
resources: barConfig.popouts.resources,
clock: barConfig.popouts.clock,
network: barConfig.popouts.network,
upower: barConfig.popouts.upower
},
entries: barConfig.entries
};
}
function serializeClipboard(): var {
return {
enabled: clipboard.enabled,
maxEntriesShown: clipboard.maxEntriesShown,
sizes: {
width: clipboard.sizes.width,
previewWidth: clipboard.sizes.previewWidth,
minPreviewWidth: clipboard.sizes.minPreviewWidth,
itemHeight: clipboard.sizes.itemHeight
}
};
}
function serializeColors(): var {
return {
schemeType: colors.schemeType,
presets: {
name: colors.presets.name,
variant: colors.presets.variant,
accent: colors.presets.accent
}
};
}
function serializeConfig(): var {
return {
barConfig: serializeBar(),
lock: serializeLock(),
general: serializeGeneral(),
services: serializeServices(),
notifs: serializeNotifs(),
sidebar: serializeSidebar(),
utilities: serializeUtilities(),
dashboard: serializeDashboard(),
appearance: serializeAppearance(),
osd: serializeOsd(),
background: serializeBackground(),
launcher: serializeLauncher(),
colors: serializeColors(),
dock: serializeDock(),
screenshot: serializeScreenshot(),
clipboard: serializeClipboard()
};
}
function serializeDashboard(): var {
return {
enabled: dashboard.enabled,
mediaUpdateInterval: dashboard.mediaUpdateInterval,
resourceUpdateInterval: dashboard.resourceUpdateInterval,
dragThreshold: dashboard.dragThreshold,
performance: {
showBattery: dashboard.performance.showBattery,
showGpu: dashboard.performance.showGpu,
showCpu: dashboard.performance.showCpu,
showMemory: dashboard.performance.showMemory,
showStorage: dashboard.performance.showStorage,
showNetwork: dashboard.performance.showNetwork
},
sizes: {
tabIndicatorHeight: dashboard.sizes.tabIndicatorHeight,
tabIndicatorSpacing: dashboard.sizes.tabIndicatorSpacing,
infoWidth: dashboard.sizes.infoWidth,
infoIconSize: dashboard.sizes.infoIconSize,
dateTimeWidth: dashboard.sizes.dateTimeWidth,
mediaWidth: dashboard.sizes.mediaWidth,
mediaProgressSweep: dashboard.sizes.mediaProgressSweep,
mediaProgressThickness: dashboard.sizes.mediaProgressThickness,
resourceProgessThickness: dashboard.sizes.resourceProgessThickness,
weatherWidth: dashboard.sizes.weatherWidth,
mediaCoverArtSize: dashboard.sizes.mediaCoverArtSize,
mediaVisualizerSize: dashboard.sizes.mediaVisualizerSize,
resourceSize: dashboard.sizes.resourceSize
}
};
}
function serializeDock(): var {
return {
enable: dock.enable,
height: dock.height,
hoverToReveal: dock.hoverToReveal,
pinnedApps: dock.pinnedApps,
pinnedOnStartup: dock.pinnedOnStartup,
ignoredAppRegexes: dock.ignoredAppRegexes
};
}
function serializeGeneral(): var {
return {
logo: general.logo,
wallpaperPath: general.wallpaperPath,
showOverFullscreen: general.showOverFullscreen,
desktopIcons: general.desktopIcons,
dateFormat: general.dateFormat,
color: {
mode: general.color.mode,
smart: general.color.smart,
scheduleDark: general.color.scheduleDark,
scheduleHyprsunset: general.color.scheduleHyprsunset,
scheduleHyprsunsetStart: general.color.scheduleHyprsunsetStart,
hyprsunsetTemp: general.color.hyprsunsetTemp,
scheduleHyprsunsetEnd: general.color.scheduleHyprsunsetEnd,
schemeGeneration: general.color.schemeGeneration,
scheduleDarkStart: general.color.scheduleDarkStart,
scheduleDarkEnd: general.color.scheduleDarkEnd,
neovimColors: general.color.neovimColors
},
apps: {
terminal: general.apps.terminal,
audio: general.apps.audio,
playback: general.apps.playback,
explorer: general.apps.explorer
},
idle: {
timeouts: general.idle.timeouts
},
battery: {
popupThresholds: general.battery.popupThresholds,
critPerc: general.battery.critPerc
}
};
}
function serializeLauncher(): var {
return {
maxAppsShown: launcher.maxAppsShown,
maxWallpapers: launcher.maxWallpapers,
uwsm: launcher.uwsm,
actionPrefix: launcher.actionPrefix,
specialPrefix: launcher.specialPrefix,
useFuzzy: {
apps: launcher.useFuzzy.apps,
actions: launcher.useFuzzy.actions,
schemes: launcher.useFuzzy.schemes,
variants: launcher.useFuzzy.variants,
wallpapers: launcher.useFuzzy.wallpapers
},
sizes: {
itemWidth: launcher.sizes.itemWidth,
itemHeight: launcher.sizes.itemHeight,
wallpaperWidth: launcher.sizes.wallpaperWidth,
wallpaperHeight: launcher.sizes.wallpaperHeight
},
actions: launcher.actions
};
}
function serializeLock(): var {
return {
recolorLogo: lock.recolorLogo,
enableFprint: lock.enableFprint,
showNotifContent: lock.showNotifContent,
showNotifIcon: lock.showNotifIcon,
maxFprintTries: lock.maxFprintTries,
blurAmount: lock.blurAmount,
sizes: {
heightMult: lock.sizes.heightMult,
ratio: lock.sizes.ratio,
centerWidth: lock.sizes.centerWidth
}
};
}
function serializeNotifs(): var {
return {
expire: notifs.expire,
defaultExpireTimeout: notifs.defaultExpireTimeout,
appNotifCooldown: notifs.appNotifCooldown,
clearThreshold: notifs.clearThreshold,
expandThreshold: notifs.expandThreshold,
actionOnClick: notifs.actionOnClick,
groupPreviewNum: notifs.groupPreviewNum,
sizes: {
width: notifs.sizes.width,
image: notifs.sizes.image,
badge: notifs.sizes.badge
}
};
}
function serializeOsd(): var {
return {
enabled: osd.enabled,
hideDelay: osd.hideDelay,
enableBrightness: osd.enableBrightness,
enableMicrophone: osd.enableMicrophone,
allMonBrightness: osd.allMonBrightness,
sizes: {
sliderWidth: osd.sizes.sliderWidth,
sliderHeight: osd.sizes.sliderHeight
}
};
}
function serializeScreenshot(): var {
return {
enable_pp: screenshot.enable_pp,
mode: screenshot.mode,
radius: screenshot.radius,
shadow: screenshot.shadow,
rounding: screenshot.rounding,
shadow_blur: screenshot.shadow_blur,
shadow_color: screenshot.shadow_color,
shadow_offset_x: screenshot.shadow_offset_x,
shadow_offset_y: screenshot.shadow_offset_y
};
}
function serializeServices(): var {
return {
weatherLocation: services.weatherLocation,
updates: services.updates,
useFahrenheit: services.useFahrenheit,
minBrightness: services.minBrightness,
ddcutilService: services.ddcutilService,
useTwelveHourClock: services.useTwelveHourClock,
gpuType: services.gpuType,
audioIncrement: services.audioIncrement,
brightnessIncrement: services.brightnessIncrement,
maxVolume: services.maxVolume,
defaultPlayer: services.defaultPlayer,
playerAliases: services.playerAliases,
visualizerBars: services.visualizerBars
};
}
function serializeSidebar(): var {
return {
enabled: sidebar.enabled,
sizes: {
width: sidebar.sizes.width
}
};
}
function serializeUtilities(): var {
return {
enabled: utilities.enabled,
maxToasts: utilities.maxToasts,
sizes: {
width: utilities.sizes.width,
toastWidth: utilities.sizes.toastWidth
},
toasts: {
configLoaded: utilities.toasts.configLoaded,
chargingChanged: utilities.toasts.chargingChanged,
gameModeChanged: utilities.toasts.gameModeChanged,
dndChanged: utilities.toasts.dndChanged,
audioOutputChanged: utilities.toasts.audioOutputChanged,
audioInputChanged: utilities.toasts.audioInputChanged,
capsLockChanged: utilities.toasts.capsLockChanged,
numLockChanged: utilities.toasts.numLockChanged,
kbLayoutChanged: utilities.toasts.kbLayoutChanged,
vpnChanged: utilities.toasts.vpnChanged,
nowPlaying: utilities.toasts.nowPlaying
},
vpn: {
enabled: utilities.vpn.enabled,
provider: utilities.vpn.provider
}
};
}
ElapsedTimer {
id: timer
}
Timer {
id: saveTimer
interval: 500
onTriggered: {
timer.restart();
try {
let config = {};
try {
config = JSON.parse(fileView.text());
} catch (e) {
config = {};
}
config = root.serializeConfig();
fileView.setText(JSON.stringify(config, null, 4));
} catch (e) {
Toaster.toast(qsTr("Failed to serialize config"), e.message, "settings_alert", Toast.Error);
}
}
}
Timer {
id: recentSaveCooldown
interval: 2000
onTriggered: {
root.recentlySaved = false;
}
}
FileView {
id: fileView
path: `${Paths.config}/config.json`
watchChanges: true
onFileChanged: {
if (!root.recentlySaved) {
timer.restart();
reload();
} else {
reload();
}
}
onLoadFailed: err => {
if (err !== FileViewError.FileNotFound)
Toaster.toast(qsTr("Failed to read config"), FileViewError.toString(err), "settings_alert", Toast.Warning);
}
onLoaded: {
ModeScheduler.checkStartup();
Hyprsunset.checkStartup();
try {
JSON.parse(text());
const elapsed = timer.elapsedMs();
if (adapter.utilities.toasts.configLoaded && !root.recentlySaved) {
Toaster.toast(qsTr("Config loaded"), qsTr("Config loaded in %1ms").arg(elapsed), "rule_settings");
} else if (adapter.utilities.toasts.configLoaded && root.recentlySaved) {
Toaster.toast(qsTr("Config saved"), qsTr("Config reloaded in %1ms").arg(elapsed), "settings_alert");
}
} catch (e) {
Toaster.toast(qsTr("Failed to load config"), e.message, "settings_alert", Toast.Error);
}
}
onSaveFailed: err => Toaster.toast(qsTr("Failed to save config"), FileViewError.toString(err), "settings_alert", Toast.Error)
JsonAdapter {
id: adapter
property AppearanceConf appearance: AppearanceConf {
}
property BackgroundConfig background: BackgroundConfig {
}
property BarConfig barConfig: BarConfig {
}
property ClipboardConfig clipboard: ClipboardConfig {
}
property Colors colors: Colors {
}
property DashboardConfig dashboard: DashboardConfig {
}
property DockConfig dock: DockConfig {
}
property General general: General {
}
property Launcher launcher: Launcher {
}
property LockConf lock: LockConf {
}
property NotifConfig notifs: NotifConfig {
}
property Osd osd: Osd {
}
property Overview overview: Overview {
}
property Screenshot screenshot: Screenshot {
}
property Services services: Services {
}
property SidebarConfig sidebar: SidebarConfig {
}
property UtilConfig utilities: UtilConfig {
}
}
}
}
-36
View File
@@ -1,36 +0,0 @@
import Quickshell.Io
JsonObject {
property int dragThreshold: 50
property bool enabled: true
property int mediaUpdateInterval: 500
property Performance performance: Performance {
}
property int resourceUpdateInterval: 1000
property Sizes sizes: Sizes {
}
component Performance: JsonObject {
property bool showBattery: true
property bool showCpu: true
property bool showGpu: true
property bool showMemory: true
property bool showNetwork: true
property bool showStorage: true
}
component Sizes: JsonObject {
readonly property int dateTimeWidth: 110
readonly property int infoIconSize: 25
readonly property int infoWidth: 200
readonly property int mediaCoverArtSize: 150
readonly property int mediaProgressSweep: 180
readonly property int mediaProgressThickness: 8
readonly property int mediaVisualizerSize: 200
readonly property int mediaWidth: 200
readonly property int resourceProgessThickness: 10
readonly property int resourceSize: 200
readonly property int tabIndicatorHeight: 3
readonly property int tabIndicatorSpacing: 5
readonly property int weatherWidth: 250
}
}
-10
View File
@@ -1,10 +0,0 @@
import Quickshell.Io
JsonObject {
property bool enable: false
property real height: 60
property bool hoverToReveal: true
property list<string> ignoredAppRegexes: []
property list<string> pinnedApps: ["org.kde.dolphin", "kitty",]
property bool pinnedOnStartup: false
}
-68
View File
@@ -1,68 +0,0 @@
import Quickshell.Io
import Quickshell
JsonObject {
property Apps apps: Apps {
}
property Battery battery: Battery {
}
property Color color: Color {
}
property string dateFormat: "ddd d MMM - hh:mm:ss"
property bool desktopIcons: false
property Idle idle: Idle {
}
property string logo: ""
property bool showOverFullscreen: true
property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers"
component Apps: JsonObject {
property list<string> archiver: ["ark"]
property list<string> audio: ["pavucontrol"]
property list<string> document: ["libreoffice"]
property list<string> editor: ["kate"]
property list<string> explorer: ["dolphin"]
property list<string> image: ["imv"]
property list<string> playback: ["mpv"]
property list<string> terminal: ["kitty"]
}
component Battery: JsonObject {
property int critPerc: 5
property list<var> popupThresholds: [
{
perc: 20,
name: qsTr("Low battery"),
message: qsTr("Battery is low"),
icon: "battery_android_frame_2"
},
]
}
component Color: JsonObject {
property int hyprsunsetTemp: 5000
property string mode: "dark"
property bool neovimColors: false
property bool scheduleDark: false
property int scheduleDarkEnd: 0
property int scheduleDarkStart: 0
property bool scheduleHyprsunset: false
property int scheduleHyprsunsetEnd: 0
property int scheduleHyprsunsetStart: 0
property bool schemeGeneration: true
property bool smart: false
}
component Idle: JsonObject {
property list<var> timeouts: [
{
name: "Lock",
timeout: 180,
idleAction: "lock"
},
{
name: "Screen",
timeout: 300,
idleAction: "dpms off",
activeAction: "dpms on"
}
]
}
}
-15
View File
@@ -1,15 +0,0 @@
import Quickshell.Io
JsonObject {
property list<var> timeouts: [
{
timeout: 180,
idleAction: "lock"
},
{
timeout: 300,
idleAction: "dpms off",
activeAction: "dpms on"
}
]
}
-109
View File
@@ -1,109 +0,0 @@
import Quickshell.Io
JsonObject {
property string actionPrefix: ">"
property list<var> actions: [
{
name: "Calculator",
icon: "calculate",
description: "Do simple math equations",
command: ["autocomplete", "calc"],
enabled: true,
dangerous: false
},
{
name: "Light",
icon: "light_mode",
description: "Change to light mode",
command: ["setMode", "light"],
enabled: true,
dangerous: false
},
{
name: "Dark",
icon: "dark_mode",
description: "Change to dark mode",
command: ["setMode", "dark"],
enabled: true,
dangerous: false
},
{
name: "Wallpaper",
icon: "image",
description: "Change the current wallpaper",
command: ["autocomplete", "wallpaper"],
enabled: true,
dangerous: false
},
{
name: "Variant",
icon: "colors",
description: "Change the current scheme variant",
command: ["autocomplete", "variant"],
enabled: true,
dangerous: false
},
{
name: "Shutdown",
icon: "power_settings_new",
description: "Shutdown the system",
command: ["systemctl", "poweroff"],
enabled: true,
dangerous: true
},
{
name: "Reboot",
icon: "cached",
description: "Reboot the system",
command: ["systemctl", "reboot"],
enabled: true,
dangerous: true
},
{
name: "Logout",
icon: "logout",
description: "Log out of the current session",
command: ["loginctl", "terminate-user", ""],
enabled: true,
dangerous: true
},
{
name: "Lock",
icon: "lock",
description: "Lock the current session",
command: ["loginctl", "lock-session"],
enabled: true,
dangerous: false
},
{
name: "Sleep",
icon: "bedtime",
description: "Suspend then hibernate",
command: ["systemctl", "suspend-then-hibernate"],
enabled: true,
dangerous: false
},
]
property int maxAppsShown: 10
property int maxWallpapers: 7
property Sizes sizes: Sizes {
}
property string specialPrefix: "@"
property UseFuzzy useFuzzy: UseFuzzy {
}
property bool uwsm: true
component Sizes: JsonObject {
property int itemHeight: 50
property int itemWidth: 600
property int wallpaperHeight: 200
property int wallpaperWidth: 280
}
component UseFuzzy: JsonObject {
property bool actions: false
property bool apps: false
property bool schemes: false
property bool variants: false
property bool wallpapers: false
}
}
-18
View File
@@ -1,18 +0,0 @@
import Quickshell.Io
JsonObject {
property int blurAmount: 40
property bool enableFprint: true
property int maxFprintTries: 3
property bool recolorLogo: false
property bool showNotifContent: false
property bool showNotifIcon: true
property Sizes sizes: Sizes {
}
component Sizes: JsonObject {
property int centerWidth: 600
property real heightMult: 0.7
property real ratio: 16 / 9
}
}
-26
View File
@@ -1,26 +0,0 @@
pragma Singleton
import Quickshell
Singleton {
id: root
readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
readonly property int emphasizedAccelTime: 200 * scale
readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
readonly property int emphasizedDecelTime: 400 * scale
readonly property int emphasizedTime: 500 * scale
readonly property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1.00, 1, 1]
readonly property int expressiveDefaultSpatialTime: 500 * scale
readonly property list<real> expressiveEffects: [0.34, 0.80, 0.34, 1.00, 1, 1]
readonly property int expressiveEffectsTime: 200 * scale
readonly property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.90, 1, 1]
readonly property int expressiveFastSpatialTime: 350 * scale
property real scale: Appearance.anim.durations.scale
readonly property list<real> standard: [0.2, 0, 0, 1, 1, 1]
readonly property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
readonly property int standardAccelTime: 200 * scale
readonly property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
readonly property int standardDecelTime: 250 * scale
readonly property int standardTime: 300 * scale
}
-20
View File
@@ -1,20 +0,0 @@
import Quickshell.Io
JsonObject {
property bool actionOnClick: false
property int appNotifCooldown: 0
property real clearThreshold: 0.3
property int defaultExpireTimeout: 5000
property int expandThreshold: 20
property bool expire: true
property int groupPreviewNum: 3
property bool openExpanded: false
property Sizes sizes: Sizes {
}
component Sizes: JsonObject {
property int badge: 20
property int image: 41
property int width: 400
}
}
-16
View File
@@ -1,16 +0,0 @@
import Quickshell.Io
JsonObject {
property bool allMonBrightness: false
property bool enableBrightness: true
property bool enableMicrophone: true
property bool enabled: true
property int hideDelay: 3000
property Sizes sizes: Sizes {
}
component Sizes: JsonObject {
property int sliderHeight: 150
property int sliderWidth: 30
}
}
-8
View File
@@ -1,8 +0,0 @@
import Quickshell.Io
JsonObject {
property int columns: 5
property bool enable: false
property int rows: 2
property real scale: 0.16
}
-13
View File
@@ -1,13 +0,0 @@
import Quickshell.Io
JsonObject {
property bool enable_pp: true
property string mode: "manual"
property real radius: 12.0
property bool rounding: false
property bool shadow: true
property real shadow_blur: 22.0
property list<int> shadow_color: [0, 0, 0, 160]
property real shadow_offset_x: 5.0
property real shadow_offset_y: 5.0
}
-23
View File
@@ -1,23 +0,0 @@
import Quickshell.Io
import QtQuick
JsonObject {
property real audioIncrement: 0.1
property real brightnessIncrement: 0.1
property bool ddcutilService: false
property string defaultPlayer: "Spotify"
property string gpuType: ""
property real maxVolume: 1.0
property real minBrightness: 0.01
property list<var> playerAliases: [
{
"from": "com.github.th_ch.youtube_music",
"to": "YT Music"
}
]
property bool updates: true
property bool useFahrenheit: false
property bool useTwelveHourClock: Qt.locale().timeFormat(Locale.ShortFormat).toLowerCase().includes("a")
property int visualizerBars: 30
property string weatherLocation: ""
}
-11
View File
@@ -1,11 +0,0 @@
import Quickshell.Io
JsonObject {
property bool enabled: true
property Sizes sizes: Sizes {
}
component Sizes: JsonObject {
property int width: 430
}
}
-7
View File
@@ -1,7 +0,0 @@
import Quickshell.Io
JsonObject {
property real base: 0.85
property bool enabled: false
property real layers: 0.4
}
-35
View File
@@ -1,35 +0,0 @@
import Quickshell.Io
JsonObject {
property bool enabled: true
property int maxToasts: 4
property Sizes sizes: Sizes {
}
property Toasts toasts: Toasts {
}
property Vpn vpn: Vpn {
}
component Sizes: JsonObject {
property int toastWidth: 430
property int width: 430
}
component Toasts: JsonObject {
property bool audioInputChanged: true
property bool audioOutputChanged: true
property bool capsLockChanged: true
property bool chargingChanged: true
property bool configLoaded: true
property bool dndChanged: true
property bool gameModeChanged: true
property bool kbLayoutChanged: true
property bool kbLimit: true
property bool nowPlaying: false
property bool numLockChanged: true
property bool vpnChanged: true
}
component Vpn: JsonObject {
property bool enabled: false
property list<var> provider: ["netbird"]
}
}
-6
View File
@@ -1,6 +0,0 @@
import Quickshell.Io
JsonObject {
property string inactiveTextColor: "white"
property string textColor: "black"
}
+1 -1
View File
@@ -5,7 +5,7 @@ import ZShell
import Quickshell import Quickshell
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import QtQuick import QtQuick
import qs.Config import ZShell.Config
Singleton { Singleton {
id: root id: root
+1 -1
View File
@@ -2,7 +2,7 @@ import Quickshell
import Quickshell.Services.UPower import Quickshell.Services.UPower
import QtQuick import QtQuick
import ZShell import ZShell
import qs.Config import ZShell.Config
import qs.Components.Toast import qs.Components.Toast
import qs.Helpers import qs.Helpers
+2 -7
View File
@@ -11,7 +11,7 @@ import qs.Components
import qs.Modules import qs.Modules
import qs.Helpers import qs.Helpers
import qs.Paths import qs.Paths
import qs.Config import ZShell.Config
Singleton { Singleton {
id: root id: root
@@ -25,7 +25,7 @@ Singleton {
property alias server: server property alias server: server
function shouldThrottle(appName: string): bool { function shouldThrottle(appName: string): bool {
if (props.dnd) if (props.dnd || [...Visibilities.screens.values()].some(v => v.sidebar))
return false; return false;
const key = (appName || "unknown").trim().toLowerCase(); const key = (appName || "unknown").trim().toLowerCase();
@@ -49,11 +49,6 @@ Singleton {
if (loaded) { if (loaded) {
saveTimer.restart(); saveTimer.restart();
} }
if (root.list.length > 0) {
HasNotifications.hasNotifications = true;
} else {
HasNotifications.hasNotifications = false;
}
} }
Timer { Timer {
+33 -2
View File
@@ -11,15 +11,46 @@ Variants {
required property ShellScreen modelData required property ShellScreen modelData
function rebuild(): void {
loader.active = false;
loader.active = true;
}
LazyLoader {
id: loader
active: true
Drawer {
screen: scope.modelData
}
}
Connections {
function onConfigPositionChanged(): void {
Qt.callLater(scope.rebuild);
}
target: (loader.item as Drawer)?.geometry ?? null
}
}
component Drawer: Scope {
id: drawer
readonly property alias geometry: content.geometry
required property ShellScreen screen
Exclusions { Exclusions {
bar: content.bar bar: content.bar
screen: scope.modelData geometry: content.geometry
screen: drawer.screen
} }
Windows { Windows {
id: content id: content
screen: scope.modelData screen: drawer.screen
} }
} }
} }
+55
View File
@@ -0,0 +1,55 @@
import QtQuick
import qs.Modules.Bar as Bar
QtObject {
id: root
required property Bar.BarLoader bar
readonly property real barClamped: bar.clampedExtent
readonly property real barExtent: bar.extent
readonly property bool barOnBottom: position === "bottom"
readonly property bool barOnLeft: position === "left"
readonly property bool barOnTop: position === "top"
required property string configPosition
readonly property bool horizontal: position !== "left"
readonly property string position: configPosition === "top" || configPosition === "bottom" ? configPosition : "left"
required property var win
function axisPos(x: real, y: real): real {
return horizontal ? x : y;
}
function barContains(x: real, y: real, clamped = false): bool {
const extent = clamped ? barClamped : barExtent;
if (barOnTop)
return y < extent;
if (barOnBottom)
return y > win.height - extent;
return x < extent;
}
function insetBottom(border: real, clamped = false): real {
return barOnBottom ? (clamped ? barClamped : barExtent) : border;
}
function insetLeft(border: real, clamped = false): real {
return barOnLeft ? (clamped ? barClamped : barExtent) : border;
}
function insetTop(border: real, clamped = false): real {
return barOnTop ? (clamped ? barClamped : barExtent) : border;
}
function inwardDrag(dragX: real, dragY: real): real {
if (barOnTop)
return dragY;
if (barOnBottom)
return -dragY;
return dragX;
}
onConfigPositionChanged: {
if (!["left", "top", "bottom"].includes(configPosition))
console.warn(`Invalid bar position '${configPosition}', falling back to left`);
}
}
+8 -3
View File
@@ -2,26 +2,28 @@ pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import QtQuick import QtQuick
import qs.Config import ZShell.Config
import qs.Components import qs.Components
Scope { Scope {
id: root id: root
required property Item bar required property Item bar
required property EdgeGeometry geometry
required property ShellScreen screen required property ShellScreen screen
ExclusionZone { ExclusionZone {
id: top id: top
anchors.top: true anchors.top: true
exclusiveZone: root.bar.exclusiveZone hasBar: root.geometry.barOnTop
} }
ExclusionZone { ExclusionZone {
id: left id: left
anchors.left: true anchors.left: true
hasBar: root.geometry.barOnLeft
} }
ExclusionZone { ExclusionZone {
@@ -34,6 +36,7 @@ Scope {
id: bottom id: bottom
anchors.bottom: true anchors.bottom: true
hasBar: root.geometry.barOnBottom
} }
Timer { Timer {
@@ -44,7 +47,9 @@ Scope {
} }
component ExclusionZone: CustomWindow { component ExclusionZone: CustomWindow {
exclusiveZone: Config.barConfig.border property bool hasBar
exclusiveZone: hasBar ? root.bar.exclusiveZone : Config.bar.border
implicitHeight: 1 implicitHeight: 1
implicitWidth: 1 implicitWidth: 1
name: "Bar-Exclusion" name: "Bar-Exclusion"
+33 -40
View File
@@ -1,9 +1,9 @@
import Quickshell import Quickshell
import QtQuick import QtQuick
import qs.Components import qs.Components
import qs.Config import ZShell.Config
import qs.Helpers import qs.Helpers
import qs.Modules as BarPopouts import qs.Modules.Bar.Popouts
Item { Item {
id: root id: root
@@ -12,43 +12,47 @@ Item {
required property real borderThickness required property real borderThickness
property bool dashboardShortcutActive property bool dashboardShortcutActive
required property Drawing drawing required property Drawing drawing
required property EdgeGeometry geometry
property bool osdShortcutActive property bool osdShortcutActive
required property Panels panels required property Panels panels
required property BarPopouts.Wrapper popouts required property Wrapper popouts
required property ShellScreen screen required property ShellScreen screen
property bool singleGestureTriggered: false property bool singleGestureTriggered: false
property bool utilitiesShortcutActive property bool utilitiesShortcutActive
required property PersistentProperties visibilities required property PersistentProperties visibilities
function inBottomPanel(panel: Item, x: real, y: real): bool { function inBottomPanel(panel: Item, x: real, y: real): bool {
return y > root.height - panel.height - Config.barConfig.border && withinPanelWidth(panel, x, y); const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0));
return y > root.height - (panelHeight + geometry.insetBottom(borderThickness)) && withinPanelWidth(panel, x, y);
} }
function inLeftPanel(panel: Item, x: real, y: real): bool { function inLeftPanel(panel: Item, x: real, y: real): bool {
return x < panel.x + panel.width + Config.barConfig.border && withinPanelHeight(panel, x, y); return x < panel.x + panel.width + geometry.insetLeft(borderThickness) && withinPanelHeight(panel, x, y);
}
function inPopoutArea(x: real, y: real): bool {
const panel = panels.popoutsWrapper;
if (!geometry.horizontal)
return inLeftPanel(panel, x, y);
return withinPanelWidth(panel, x, y) && withinPanelHeight(panel, x, y);
} }
function inRightPanel(panel: Item, x: real, y: real): bool { function inRightPanel(panel: Item, x: real, y: real): bool {
return x > panel.x - Config.barConfig.border && withinPanelHeight(panel, x, y); return x > panel.x + geometry.insetLeft(borderThickness) && withinPanelHeight(panel, x, y);
} }
function inTopPanel(panel: Item, x: real, y: real): bool { function inTopPanel(panel: Item, x: real, y: real): bool {
return y < bar.implicitHeight + panel.height && withinPanelWidth(panel, x, y); const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0));
} return y < geometry.insetTop(borderThickness) + panelHeight && withinPanelWidth(panel, x, y);
function onWheel(event: WheelEvent): void {
if (event.x < bar.implicitWidth) {
bar.handleWheel(event.y, event.angleDelta);
}
} }
function withinPanelHeight(panel: Item, x: real, y: real): bool { function withinPanelHeight(panel: Item, x: real, y: real): bool {
const panelY = panel.y + bar.implicitHeight; const panelY = panel.y + geometry.insetTop(borderThickness);
return y >= panelY && y <= panelY + panel.height; return y >= panelY && y <= panelY + panel.height;
} }
function withinPanelWidth(panel: Item, x: real, y: real): bool { function withinPanelWidth(panel: Item, x: real, y: real): bool {
const panelX = panel.x + root.borderThickness; const panelX = panel.x + geometry.insetLeft(borderThickness);
return x >= panelX && x <= panelX + panel.width; return x >= panelX && x <= panelX + panel.width;
} }
@@ -75,13 +79,13 @@ Item {
const dragX = x - centroid.pressPosition.x; const dragX = x - centroid.pressPosition.x;
const dragY = y - centroid.pressPosition.y; const dragY = y - centroid.pressPosition.y;
if (centroid.pressPosition.y >= root.screen.height - Config.barConfig.border && centroid.pressPosition.x > root.screen.width / 5 && dragY < -200) if (centroid.pressPosition.y >= root.screen.height - Config.bar.border && centroid.pressPosition.x > root.screen.width / 5 && dragY < -Config.launcher.dragThreshold)
root.visibilities.launcher = true; root.visibilities.launcher = true;
if (root.singleGestureTriggered) if (root.singleGestureTriggered)
return; return;
if (centroid.pressPosition.y < root.bar.implicitHeight) { if (root.geometry.insetTop(root.borderThickness) > centroid.pressPosition.y) {
if (dragY > 20) { if (dragY > 20) {
root.visibilities.settings = true; root.visibilities.settings = true;
root.singleGestureTriggered = true; root.singleGestureTriggered = true;
@@ -91,26 +95,26 @@ Item {
} }
} }
if (centroid.pressPosition.y > root.screen.height - Config.barConfig.border && centroid.pressPosition.x < root.screen.width / 5 && dragY < -50) if (centroid.pressPosition.y > root.screen.height - root.geometry.insetBottom(root.borderThickness) && centroid.pressPosition.x < root.screen.width / 5 && dragY < -50)
root.visibilities.clipboard = true; root.visibilities.clipboard = true;
if (!Config.dock.hoverToReveal && centroid.pressPosition.y > root.screen.height - root.bar.implicitHeight && centroid.pressPosition.x > root.screen.width / 5 && !root.visibilities.launcher) if (!Config.dock.hoverToReveal && centroid.pressPosition.y > root.screen.height - root.geometry.insetTop(root.borderThickness) && centroid.pressPosition.x > root.screen.width / 5 && !root.visibilities.launcher)
if (dragY < -10) { if (dragY < -10) {
root.visibilities.dock = true; root.visibilities.dock = true;
root.singleGestureTriggered = true; root.singleGestureTriggered = true;
} }
if (centroid.pressPosition.x > root.screen.width - Config.barConfig.border && centroid.pressPosition.y < (root.screen.height / 2) && dragX < -20) { if (centroid.pressPosition.x > root.screen.width - Config.bar.border && centroid.pressPosition.y < (root.screen.height / 2) && dragX < -Config.sidebar.dragThreshold) {
root.visibilities.sidebar = true; root.visibilities.sidebar = true;
root.singleGestureTriggered = true; root.singleGestureTriggered = true;
} }
if (centroid.pressPosition.x >= root.screen.width - Config.barConfig.border && centroid.pressPosition.y > (root.screen.height / 2) && dragX < -20) { if (centroid.pressPosition.x >= root.screen.width - Config.bar.border && centroid.pressPosition.y > (root.screen.height / 2) && dragX < -20) {
Hypr.dispatch(`hl.dsp.focus({ workspace = 'r+1', on_current_monitor = true })`); Hypr.dispatch(`hl.dsp.focus({ workspace = 'r+1', on_current_monitor = true })`);
root.singleGestureTriggered = true; root.singleGestureTriggered = true;
} }
if (centroid.pressPosition.x <= Config.barConfig.border && dragX > 20) { if (centroid.pressPosition.x <= Config.bar.border && dragX > 20) {
Hypr.dispatch(`hl.dsp.focus({ workspace = 'r-1', on_current_monitor = true })`); Hypr.dispatch(`hl.dsp.focus({ workspace = 'r-1', on_current_monitor = true })`);
root.singleGestureTriggered = true; root.singleGestureTriggered = true;
} }
@@ -170,11 +174,11 @@ Item {
root.panels.osd.hovered = false; root.panels.osd.hovered = false;
} }
if (!root.popouts.currentName.startsWith("traymenu")) { if (!root.popouts.currentName.startsWith("traymenu") || Config.bar.tray.showOnHover) {
root.popouts.hasCurrent = false; root.popouts.hasCurrent = false;
} }
if (Config.barConfig.autoHide) if (Config.bar.autoHide)
root.bar.isHovered = false; root.bar.isHovered = false;
} }
} }
@@ -193,10 +197,10 @@ Item {
return; return;
} }
if (!root.visibilities.bar && Config.barConfig.autoHide && y < root.bar.implicitHeight) if (!root.visibilities.bar && Config.bar.autoHide && root.geometry.barContains(x, y, true))
root.bar.isHovered = true; root.bar.isHovered = true;
if (root.panels.sidebar.width === 0) { if (root.panels.sidebar.offsetScale === 1) {
const showOsd = root.inRightPanel(root.panels.osdWrapper, x, y); const showOsd = root.inRightPanel(root.panels.osdWrapper, x, y);
if (showOsd) { if (showOsd) {
@@ -204,7 +208,7 @@ Item {
root.panels.osd.hovered = true; root.panels.osd.hovered = true;
} }
} else { } else {
const outOfSidebar = x < root.width - root.panels.sidebar.width; const outOfSidebar = x < root.width - root.panels.sidebar.width * (1 - root.panels.sidebar.offsetScale);
const showOsd = outOfSidebar && root.inRightPanel(root.panels.osdWrapper, x, y); const showOsd = outOfSidebar && root.inRightPanel(root.panels.osdWrapper, x, y);
if (!root.osdShortcutActive) { if (!root.osdShortcutActive) {
@@ -219,8 +223,8 @@ Item {
if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y)) if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
root.visibilities.dock = true; root.visibilities.dock = true;
if (y < root.bar.implicitHeight) if (root.geometry.barContains(x, y))
root.bar.checkPopout(x); root.bar.checkPopout(root.geometry.axisPos(x, y));
} }
} }
@@ -309,17 +313,6 @@ Item {
} }
} }
function onUtilitiesChanged() {
if (root.visibilities.utilities) {
const inUtilitiesArea = root.inBottomPanel(root.panels.utilities, root.mouseX, root.mouseY);
if (!inUtilitiesArea) {
root.utilitiesShortcutActive = true;
}
} else {
root.utilitiesShortcutActive = false;
}
}
target: root.visibilities target: root.visibilities
} }
} }
+26 -27
View File
@@ -1,7 +1,7 @@
import Quickshell import Quickshell
import QtQuick import QtQuick
import qs.Components import qs.Components
import qs.Modules as Modules import qs.Modules.Bar.Popouts as Popouts
import qs.Modules.Notifications as Notifications import qs.Modules.Notifications as Notifications
import qs.Modules.Notifications.Sidebar as Sidebar import qs.Modules.Notifications.Sidebar as Sidebar
import qs.Modules.Notifications.Sidebar.Utils as Utils import qs.Modules.Notifications.Sidebar.Utils as Utils
@@ -14,7 +14,7 @@ import qs.Modules.Settings as Settings
import qs.Modules.Drawing as Drawing import qs.Modules.Drawing as Drawing
import qs.Modules.Dock as Dock import qs.Modules.Dock as Dock
import qs.Modules.Clipboard as Clipboard import qs.Modules.Clipboard as Clipboard
import qs.Config import ZShell.Config
Item { Item {
id: root id: root
@@ -27,6 +27,7 @@ Item {
readonly property alias dock: dock readonly property alias dock: dock
readonly property alias drawing: drawing readonly property alias drawing: drawing
required property var drawingItem required property var drawingItem
required property EdgeGeometry geometry
readonly property alias launcher: launcher readonly property alias launcher: launcher
readonly property alias notifications: notifications readonly property alias notifications: notifications
readonly property alias osd: osd readonly property alias osd: osd
@@ -43,24 +44,26 @@ Item {
readonly property alias utilities: utilities readonly property alias utilities: utilities
required property PersistentProperties visibilities required property PersistentProperties visibilities
anchors.bottomMargin: geometry.insetBottom(borderThickness)
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: geometry.insetLeft(borderThickness)
anchors.margins: borderThickness anchors.margins: borderThickness
anchors.topMargin: bar.implicitHeight anchors.topMargin: geometry.insetTop(borderThickness)
Item { Item {
id: resourcesWrapper id: resourcesWrapper
anchors.bottom: root.geometry.position === "bottom" ? parent.bottom : undefined
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: root.geometry.position !== "bottom" ? parent.top : undefined
clip: true clip: true
implicitHeight: resources.implicitHeight * (1 - resources.offsetScale) implicitHeight: root.geometry.horizontal ? resources.implicitHeight * (1 - resources.offsetScale) : resources.implicitHeight
implicitWidth: resources.implicitWidth implicitWidth: root.geometry.horizontal ? resources.implicitWidth : resources.implicitWidth * (1 - resources.offsetScale)
Resources.Wrapper { Resources.Wrapper {
id: resources id: resources
anchors.left: parent.left position: root.geometry.position
anchors.top: parent.top
visibilities: root.visibilities visibilities: root.visibilities
} }
} }
@@ -96,11 +99,11 @@ Item {
visibilities: root.visibilities visibilities: root.visibilities
} }
Modules.ClipWrapper { Popouts.ClipWrapper {
id: popouts id: popouts
anchors.top: parent.top
borderThickness: root.borderThickness borderThickness: root.borderThickness
position: root.geometry.position
screen: root.screen screen: root.screen
} }
@@ -108,7 +111,7 @@ Item {
id: toasts id: toasts
anchors.bottom: sidebar.visible ? parent.bottom : utilities.top anchors.bottom: sidebar.visible ? parent.bottom : utilities.top
anchors.margins: Appearance.padding.normal anchors.margins: Tokens.padding.normal
anchors.right: sidebar.left anchors.right: sidebar.left
} }
@@ -147,26 +150,26 @@ Item {
property real offsetScale: dashboard.shouldBeActive ? 0 : 1 property real offsetScale: dashboard.shouldBeActive ? 0 : 1
anchors.right: parent.right anchors.bottom: root.geometry.barOnLeft || root.geometry.barOnBottom ? parent.bottom : undefined
anchors.top: parent.top anchors.left: root.geometry.barOnLeft ? parent.left : undefined
anchors.right: root.geometry.barOnLeft ? undefined : parent.right
anchors.top: root.geometry.barOnBottom || root.geometry.barOnLeft ? undefined : parent.top
clip: true clip: true
implicitHeight: dashboard.implicitHeight * (1 - offsetScale) implicitHeight: root.geometry.horizontal ? dashboard.implicitHeight * (1 - offsetScale) : dashboard.implicitHeight
implicitWidth: dashboard.implicitWidth implicitWidth: root.geometry.horizontal ? dashboard.implicitWidth : dashboard.implicitWidth * (1 - offsetScale)
Behavior on offsetScale { Behavior on offsetScale {
Anim { Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
Dashboard.Wrapper { Dashboard.Wrapper {
id: dashboard id: dashboard
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: (-implicitHeight - 5) * offsetScale
offsetScale: dashboardWrapper.offsetScale offsetScale: dashboardWrapper.offsetScale
position: root.geometry.position
visibilities: root.visibilities visibilities: root.visibilities
} }
} }
@@ -184,18 +187,14 @@ Item {
Item { Item {
id: settingsWrapper id: settingsWrapper
anchors.horizontalCenter: parent.horizontalCenter anchors.fill: parent
anchors.top: parent.top
clip: true clip: true
implicitHeight: settings.implicitHeight * (1 - settings.offsetScale)
implicitWidth: settings.implicitWidth
Settings.Wrapper { Settings.Wrapper {
id: settings id: settings
anchors.horizontalCenter: parent.horizontalCenter anchors.centerIn: parent
anchors.top: parent.top anchors.verticalCenterOffset: (-implicitHeight - 5 - ((root.height - implicitHeight) / 2)) * offsetScale
// anchors.centerIn: parent
panels: root panels: root
screen: root.screen screen: root.screen
visibilities: root.visibilities visibilities: root.visibilities
+93
View File
@@ -0,0 +1,93 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Modules.Bar as Bar
Region {
id: root
// required property Bar.BarLoader bar
readonly property real borderThickness: win.borderThickness
required property EdgeGeometry geometry
readonly property alias menuPopoutRegion: menuPopoutRegion
required property Panels panels
required property var win
height: win.height - geometry.insetTop(borderThickness, true) - geometry.insetBottom(borderThickness, true) - win.dragMaskPadding * 2
intersection: Intersection.Xor
width: win.width - geometry.insetLeft(borderThickness, true) * 2 - win.dragMaskPadding * 2
x: geometry.insetLeft(borderThickness, true) + win.dragMaskPadding
y: geometry.insetTop(borderThickness, true) + win.dragMaskPadding
R {
panel: root.panels.dashboardWrapper
}
R {
panel: root.panels.launcher
}
R {
id: sidebarRegion
panel: root.panels.sidebar
width: panel.width * (1 - root.panels.sidebar.offsetScale) + root.borderThickness
x: root.win.width - width
}
R {
panel: root.panels.osdWrapper
width: panel.width * (1 - root.panels.osd.offsetScale) + root.borderThickness
}
R {
height: panel.height + root.geometry.insetTop(root.borderThickness)
panel: root.panels.notifications
y: 0
}
R {
height: panel.height * (1 - root.panels.utilities.offsetScale) + root.geometry.insetBottom(root.borderThickness)
panel: root.panels.utilities
y: root.win.height - height
}
R {
height: root.geometry.horizontal ? panel.height * (1 - root.panels.popoutsWrapper.offsetScale) : panel.height
panel: root.panels.popoutsWrapper
width: root.geometry.horizontal ? panel.width : panel.width * (1 - root.panels.popoutsWrapper.offsetScale)
}
R {
panel: root.panels.resourcesWrapper
}
R {
panel: root.panels.settings
}
R {
panel: root.panels.dock
}
R {
panel: root.panels.clipboard
}
Region {
id: menuPopoutRegion
intersection: Intersection.Subtract
}
component R: Region {
required property Item panel
height: panel.height
intersection: Intersection.Subtract
width: panel.width
x: panel.x + root.geometry.insetLeft(root.borderThickness)
y: panel.y + root.geometry.insetTop(root.borderThickness)
}
}

Some files were not shown because too many files have changed in this diff Show More