.
diff --git a/dots/quickshell/README.md b/dots/quickshell/README.md
deleted file mode 100644
index 799d1ac..0000000
--- a/dots/quickshell/README.md
+++ /dev/null
@@ -1,123 +0,0 @@
-caelestia-shell
-
-
-
-
-
-
-
-
-
-
-> [!WARNING]
-> The overhaul is finished!
-> Installation is now via an [install script](https://github.com/caelestia-dots/caelestia/blob/main/install.fish) in the
-> [`caelestia` repo](https://github.com/caelestia-dots/caelestia).
->
-> Anyone with an existing installation, please reinstall via the install script.
->
-> Some breaking changes:
-> - Rename the `scripts` repo -> `cli`
-> - Rename the `hypr` repo -> `caelestia`
-> - Merge all other repos (except this and `cli`) into `caelestia`
-> - Installation for the `shell` and `cli` will be done via AUR packages; `caelestia` will have a meta package and an install script (should fix most installation issues)
-> - Overhaul the scheme system (should fix a few bugs with that and make it cleaner in general)
-
-https://github.com/user-attachments/assets/0840f496-575c-4ca6-83a8-87bb01a85c5f
-
-## Components
-
-- Widgets: [`Quickshell`](https://quickshell.outfoxxed.me)
-- Window manager: [`Hyprland`](https://hyprland.org)
-- Dots: [`caelestia`](https://github.com/caelestia-dots)
-
-## Installation
-
-This is not implemented as of now.
-
-## Usage
-
-The shell can be started in two ways: via systemd or manually running `caelestia shell`.
-
-### Via systemd
-
-The install script creates and enables the systemd service `caelestia-shell.service` which should automatically start the
-shell on login.
-
-### Via command
-
-If not on a system that uses systemd, you can manually start the shell via `caelestia-shell`.
-To autostart it on login, you can use an `exec-once` rule in your Hyprland config:
-```
-exec-once = caelestia shell
-```
-
-### Shortcuts/IPC
-
-All keybinds are accessible via Hyprland [global shortcuts](https://wiki.hyprland.org/Configuring/Binds/#dbus-global-shortcuts).
-For a preconfigured setup, install [`caelestia-hypr`](https://github.com/caelestia-dots/hypr) via `caelestia install hypr` or see
-[this file](https://github.com/caelestia-dots/hypr/blob/main/hyprland/keybinds.conf#L1-L29) for an example on how to use global
-shortcuts.
-
-All IPC commands can be accessed via `caelestia shell ...`. For example
-```sh
-caelestia shell mpris getActive trackTitle
-```
-
-The list of IPC commands can be shown via `caelestia shell help`:
-```
-> caelestia shell help
-target mpris
- function stop(): void
- function play(): void
- function next(): void
- function getActive(prop: string): string
- function list(): string
- function playPause(): void
- function pause(): void
- function previous(): void
-target drawers
- function list(): string
- function toggle(drawer: string): void
-target wallpaper
- function list(): string
- function get(): string
- function set(path: string): void
-target notifs
- function clear(): void
-```
-
-### PFP/Wallpapers
-
-The profile picture for the dashboard is read from the file `~/.face`, so to set it just put your image there.
-
-The wallpapers for the wallpaper switcher are read from `~/Pictures/Wallpapers`, so put your wallpapers there for
-them to show up in the switcher (you need to restart the shell after changing stuff in `~/Pictures/Wallpapers` sadly,
-no watching for changes yet).
-
-To set the wallpaper, you can use the command `caelestia wallpaper`. Use `caelestia wallpaper -h` for more info about
-the command.
-
-## Credits
-
-Thanks to the Hyprland discord community (especially the homies in #rice-discussion) for all the help and suggestions
-for improving these dots!
-
-A special thanks to [@outfoxxed](https://github.com/outfoxxed) for making Quickshell and the effort put into fixing issues
-and implementing various feature requests.
-
-Another special thanks to [@end_4](https://github.com/end-4) for his [config](https://github.com/end-4/dots-hyprland)
-which helped me a lot with learning how to use Quickshell.
-
-Finally another thank you to all the configs I took inspiration from (only one for now):
-- [Axenide/Ax-Shell](https://github.com/Axenide/Ax-Shell)
-
-## Stonks 📈
-
-
-
-
-
-
-
-
diff --git a/dots/quickshell/assets/beat_detector.cpp b/dots/quickshell/assets/beat_detector.cpp
deleted file mode 100755
index 4eb9b48..0000000
--- a/dots/quickshell/assets/beat_detector.cpp
+++ /dev/null
@@ -1,568 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-class EnhancedBeatDetector {
-private:
- static constexpr uint32_t SAMPLE_RATE = 44100;
- static constexpr uint32_t CHANNELS = 1;
-
- // PipeWire objects
- pw_main_loop* main_loop_;
- pw_context* context_;
- pw_core* core_;
- pw_stream* stream_;
-
- // Aubio objects
- std::unique_ptr tempo_;
- std::unique_ptr input_buffer_;
- std::unique_ptr output_buffer_;
-
- // Additional aubio objects for enhanced features
- std::unique_ptr onset_;
- std::unique_ptr pitch_;
- std::unique_ptr pitch_buffer_;
-
- const uint32_t buf_size_;
- const uint32_t fft_size_;
-
- static std::atomic should_quit_;
- static EnhancedBeatDetector* instance_;
-
- // Enhanced features
- std::ofstream log_file_;
- bool enable_logging_;
- bool enable_performance_stats_;
- bool enable_pitch_detection_;
- bool enable_visual_feedback_;
-
- // Performance tracking
- std::chrono::high_resolution_clock::time_point last_process_time_;
- std::vector process_times_;
- uint64_t total_beats_;
- uint64_t total_onsets_;
- std::chrono::steady_clock::time_point start_time_;
-
- // Beat analysis
- std::vector recent_bpms_;
- static constexpr size_t BPM_HISTORY_SIZE = 10;
- float last_bpm_;
- std::chrono::steady_clock::time_point last_beat_time_;
-
- // Useless Visual feedback
- std::string generate_beat_visual(float bpm, bool is_beat) {
- if (!enable_visual_feedback_) return "";
-
- std::stringstream ss;
- if (is_beat) {
- // Useless Animated beat indicator based on BPM intensity
- int intensity = static_cast(std::min(bpm / 20.0f, 10.0f));
- ss << "\r ";
- for (int i = 0; i < intensity; ++i) ss << "█";
- for (int i = intensity; i < 10; ++i) ss << "░";
- ss << " BPM: " << std::fixed << std::setprecision(1) << bpm;
- ss << " | Avg: " << get_average_bpm();
- }
- return ss.str();
- }
-
-public:
- explicit EnhancedBeatDetector(uint32_t buf_size = 512,
- bool enable_logging = true,
- bool enable_performance_stats = true,
- bool enable_pitch_detection = false,
- bool enable_visual_feedback = true)
- : main_loop_(nullptr)
- , context_(nullptr)
- , core_(nullptr)
- , stream_(nullptr)
- , tempo_(nullptr, &del_aubio_tempo)
- , input_buffer_(nullptr, &del_fvec)
- , output_buffer_(nullptr, &del_fvec)
- , onset_(nullptr, &del_aubio_onset)
- , pitch_(nullptr, &del_aubio_pitch)
- , pitch_buffer_(nullptr, &del_fvec)
- , buf_size_(buf_size)
- , fft_size_(buf_size * 2)
- , enable_logging_(enable_logging)
- , enable_performance_stats_(enable_performance_stats)
- , enable_pitch_detection_(enable_pitch_detection)
- , enable_visual_feedback_(enable_visual_feedback)
- , total_beats_(0)
- , total_onsets_(0)
- , last_bpm_(0.0f)
- {
- instance_ = this;
- recent_bpms_.reserve(BPM_HISTORY_SIZE);
- if (enable_performance_stats_) {
- process_times_.reserve(1000); // Reserve space for performance data
- }
- initialize();
- }
-
- ~EnhancedBeatDetector() {
- print_final_stats();
- cleanup();
- instance_ = nullptr;
- }
-
- // Delete copy constructor and assignment operator
- EnhancedBeatDetector(const EnhancedBeatDetector&) = delete;
- EnhancedBeatDetector& operator=(const EnhancedBeatDetector&) = delete;
-
- bool initialize() {
- start_time_ = std::chrono::steady_clock::now();
-
- // Useless Initialize logging (actually useful)
- if (enable_logging_) {
- auto now = std::chrono::system_clock::now();
- auto time_t = std::chrono::system_clock::to_time_t(now);
- std::stringstream filename;
- filename << "beat_log_" << std::put_time(std::localtime(&time_t), "%Y%m%d_%H%M%S") << ".txt";
- log_file_.open(filename.str());
- if (log_file_.is_open()) {
- log_file_ << "# Beat Detection Log - " << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S") << "\n";
- log_file_ << "# Timestamp,BPM,Onset,Pitch(Hz),ProcessTime(ms)\n";
- std::cout << " Logging to: " << filename.str() << std::endl;
- }
- }
-
- // Initialize PipeWire
- pw_init(nullptr, nullptr);
-
- main_loop_ = pw_main_loop_new(nullptr);
- if (!main_loop_) {
- std::cerr << " Failed to create main loop" << std::endl;
- return false;
- }
-
- context_ = pw_context_new(pw_main_loop_get_loop(main_loop_), nullptr, 0);
- if (!context_) {
- std::cerr << " Failed to create context" << std::endl;
- return false;
- }
-
- core_ = pw_context_connect(context_, nullptr, 0);
- if (!core_) {
- std::cerr << " Failed to connect to PipeWire" << std::endl;
- return false;
- }
-
- // Initialize Aubio objects
- tempo_.reset(new_aubio_tempo("default", fft_size_, buf_size_, SAMPLE_RATE));
- if (!tempo_) {
- std::cerr << " Failed to create aubio tempo detector" << std::endl;
- return false;
- }
-
- input_buffer_.reset(new_fvec(buf_size_));
- output_buffer_.reset(new_fvec(1));
-
- if (!input_buffer_ || !output_buffer_) {
- std::cerr << " Failed to create aubio buffers" << std::endl;
- return false;
- }
-
- // Initialize onset detection
- onset_.reset(new_aubio_onset("default", fft_size_, buf_size_, SAMPLE_RATE));
- if (!onset_) {
- std::cerr << " Failed to create aubio onset detector" << std::endl;
- return false;
- }
-
- // Initialize pitch detection if enabled
- if (enable_pitch_detection_) {
- pitch_.reset(new_aubio_pitch("default", fft_size_, buf_size_, SAMPLE_RATE));
- pitch_buffer_.reset(new_fvec(1));
- if (!pitch_ || !pitch_buffer_) {
- std::cerr << " Failed to create aubio pitch detector" << std::endl;
- return false;
- }
- aubio_pitch_set_unit(pitch_.get(), "Hz");
- }
-
- return setup_stream();
- }
-
- void run() {
- if (!main_loop_) return;
-
- print_startup_info();
- pw_main_loop_run(main_loop_);
- }
-
- void stop() {
- should_quit_ = true;
- if (main_loop_) {
- pw_main_loop_quit(main_loop_);
- }
- }
-
- static void signal_handler(int sig) {
- if (instance_) {
- std::cout << "\n Received signal " << sig << ", stopping gracefullllly..." << std::endl;
- instance_->stop();
- }
- }
-
-private:
- void print_startup_info() {
- std::cout << "\n Beat Detector Started!" << std::endl;
- std::cout << " Buffer size: " << buf_size_ << " samples" << std::endl;
- std::cout << " Sample rate: " << SAMPLE_RATE << " Hz" << std::endl;
- std::cout << " Features enabled:" << std::endl;
- std::cout << " Logging: " << (enable_logging_ ? " " : "") << std::endl;
- std::cout << " Performance stats: " << (enable_performance_stats_ ? " " : "") << std::endl;
- std::cout << " Pitch detection: " << (enable_pitch_detection_ ? " " : "") << std::endl;
- std::cout << "\n Listening for beats... Press Ctrl+C to stop.\n" << std::endl;
- }
-
- void print_final_stats() {
- if (!enable_performance_stats_) return;
-
- auto end_time = std::chrono::steady_clock::now();
- auto duration = std::chrono::duration_cast(end_time - start_time_);
-
- std::cout << "\n Final Statistics:" << std::endl;
- std::cout << " Total runtime: " << duration.count() << " seconds" << std::endl;
- std::cout << " Total beats detected: " << total_beats_ << std::endl;
- std::cout << " Total onsets detected: " << total_onsets_ << std::endl;
-
- if (!process_times_.empty()) {
- double avg_time = 0;
- for (double t : process_times_) avg_time += t;
- avg_time /= process_times_.size();
-
- auto max_time = *std::max_element(process_times_.begin(), process_times_.end());
- auto min_time = *std::min_element(process_times_.begin(), process_times_.end());
-
- std::cout << " ⚡ Average processing time: " << std::fixed << std::setprecision(3)
- << avg_time << " ms" << std::endl;
- std::cout << " 📈 Max processing time: " << max_time << " ms" << std::endl;
- std::cout << " 📉 Min processing time: " << min_time << " ms" << std::endl;
- }
-
- if (!recent_bpms_.empty()) {
- std::cout << " Final average BPM: " << get_average_bpm() << std::endl;
- }
- }
-
- float get_average_bpm() const {
- if (recent_bpms_.empty()) return 0.0f;
- float sum = 0;
- for (float bpm : recent_bpms_) sum += bpm;
- return sum / recent_bpms_.size();
- }
-
- bool setup_stream() {
- // Stream events
- static const pw_stream_events stream_events = {
- .version = PW_VERSION_STREAM_EVENTS,
- .destroy = nullptr,
- .state_changed = on_state_changed,
- .control_info = nullptr,
- .io_changed = nullptr,
- .param_changed = nullptr,
- .add_buffer = nullptr,
- .remove_buffer = nullptr,
- .process = on_process,
- .drained = nullptr,
- .command = nullptr,
- .trigger_done = nullptr,
- };
-
- stream_ = pw_stream_new_simple(
- pw_main_loop_get_loop(main_loop_),
- "enhanced-beat-detector",
- pw_properties_new(
- PW_KEY_MEDIA_TYPE, "Audio",
- PW_KEY_MEDIA_CATEGORY, "Capture",
- PW_KEY_MEDIA_ROLE, "Music",
- nullptr
- ),
- &stream_events,
- this
- );
-
- if (!stream_) {
- std::cerr << " Failed to create stream" << std::endl;
- return false;
- }
-
- // Audio format parameters
- uint8_t buffer[1024];
- spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
-
- struct spa_audio_info_raw audio_info = {};
- audio_info.format = SPA_AUDIO_FORMAT_F32_LE;
- audio_info.channels = CHANNELS;
- audio_info.rate = SAMPLE_RATE;
- audio_info.flags = 0;
-
- const spa_pod* params[1];
- params[0] = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_EnumFormat, &audio_info);
-
- if (pw_stream_connect(stream_,
- PW_DIRECTION_INPUT,
- PW_ID_ANY,
- static_cast(
- PW_STREAM_FLAG_AUTOCONNECT |
- PW_STREAM_FLAG_MAP_BUFFERS |
- PW_STREAM_FLAG_RT_PROCESS),
- params, 1) < 0) {
- std::cerr << " Failed to connect stream" << std::endl;
- return false;
- }
-
- return true;
- }
-
- static void on_state_changed(void* userdata, enum pw_stream_state /* old_state */,
- enum pw_stream_state state, const char* error) {
- auto* detector = static_cast(userdata);
-
- const char* state_emoji = " ";
- switch (state) {
- case PW_STREAM_STATE_CONNECTING: state_emoji = " "; break;
- case PW_STREAM_STATE_PAUSED: state_emoji = ""; break;
- case PW_STREAM_STATE_STREAMING: state_emoji = " "; break;
- case PW_STREAM_STATE_ERROR: state_emoji = ""; break;
- case PW_STREAM_STATE_UNCONNECTED: state_emoji = " "; break;
- }
-
- std::cout << state_emoji << " Stream state: " << pw_stream_state_as_string(state) << std::endl;
-
- if (state == PW_STREAM_STATE_ERROR) {
- std::cerr << " Stream error: " << (error ? error : "unknown") << std::endl;
- detector->stop();
- }
- }
-
- static void on_process(void* userdata) {
- auto* detector = static_cast(userdata);
- detector->process_audio();
- }
-
- void process_audio() {
- if (should_quit_) return;
-
- auto process_start = std::chrono::high_resolution_clock::now();
-
- pw_buffer* buffer = pw_stream_dequeue_buffer(stream_);
- if (!buffer) return;
-
- spa_buffer* spa_buf = buffer->buffer;
- if (!spa_buf->datas[0].data) {
- pw_stream_queue_buffer(stream_, buffer);
- return;
- }
-
- const float* audio_data = static_cast(spa_buf->datas[0].data);
- const uint32_t n_samples = spa_buf->datas[0].chunk->size / sizeof(float);
-
- // Process in chunks
- for (uint32_t offset = 0; offset + buf_size_ <= n_samples; offset += buf_size_) {
- std::memcpy(input_buffer_->data, audio_data + offset, buf_size_ * sizeof(float));
-
- // Beat detection
- aubio_tempo_do(tempo_.get(), input_buffer_.get(), output_buffer_.get());
- bool is_beat = output_buffer_->data[0] != 0.0f;
-
- // Onset detection
- aubio_onset_do(onset_.get(), input_buffer_.get(), output_buffer_.get());
- bool is_onset = output_buffer_->data[0] != 0.0f;
-
- float pitch_hz = 0.0f;
- if (enable_pitch_detection_) {
- aubio_pitch_do(pitch_.get(), input_buffer_.get(), pitch_buffer_.get());
- pitch_hz = pitch_buffer_->data[0];
- }
-
- if (is_beat) {
- total_beats_++;
- last_bpm_ = aubio_tempo_get_bpm(tempo_.get());
- last_beat_time_ = std::chrono::steady_clock::now();
-
- // Update BPM history
- recent_bpms_.push_back(last_bpm_);
- if (recent_bpms_.size() > BPM_HISTORY_SIZE) {
- recent_bpms_.erase(recent_bpms_.begin());
- }
-
- // Visual feedback
- if (enable_visual_feedback_) {
- std::cout << generate_beat_visual(last_bpm_, true) << std::flush;
- } else {
- std::cout << " BPM: " << std::fixed << std::setprecision(1) << last_bpm_ << std::endl;
- }
- }
-
- if (is_onset) {
- total_onsets_++;
- }
-
- // Logging
- if (enable_logging_ && log_file_.is_open() && (is_beat || is_onset)) {
- auto now = std::chrono::system_clock::now();
- auto time_t = std::chrono::system_clock::to_time_t(now);
- auto ms = std::chrono::duration_cast(
- now.time_since_epoch()) % 1000;
-
- log_file_ << std::put_time(std::localtime(&time_t), "%H:%M:%S")
- << "." << std::setfill('0') << std::setw(3) << ms.count() << ","
- << (is_beat ? last_bpm_ : 0) << ","
- << (is_onset ? 1 : 0) << ","
- << pitch_hz << ",";
- }
- }
-
- pw_stream_queue_buffer(stream_, buffer);
-
- // Performance tracking
- if (enable_performance_stats_) {
- auto process_end = std::chrono::high_resolution_clock::now();
- auto process_time = std::chrono::duration(process_end - process_start).count();
-
- if (log_file_.is_open() && (total_beats_ > 0 || total_onsets_ > 0)) {
- log_file_ << std::fixed << std::setprecision(3) << process_time << "\n";
- }
-
- if (process_times_.size() < 1000) {
- process_times_.push_back(process_time);
- }
- }
- }
-
- void cleanup() {
- if (log_file_.is_open()) {
- log_file_.close();
- }
-
- if (stream_) {
- pw_stream_destroy(stream_);
- stream_ = nullptr;
- }
-
- if (core_) {
- pw_core_disconnect(core_);
- core_ = nullptr;
- }
-
- if (context_) {
- pw_context_destroy(context_);
- context_ = nullptr;
- }
-
- if (main_loop_) {
- pw_main_loop_destroy(main_loop_);
- main_loop_ = nullptr;
- }
-
- tempo_.reset();
- input_buffer_.reset();
- output_buffer_.reset();
- onset_.reset();
- pitch_.reset();
- pitch_buffer_.reset();
-
- pw_deinit();
-
- std::cout << "\n Cleanup complete - All resources freed!" << std::endl;
- }
-};
-
-// Static member definitions
-std::atomic EnhancedBeatDetector::should_quit_{false};
-EnhancedBeatDetector* EnhancedBeatDetector::instance_{nullptr};
-
-void print_usage() {
- std::cout << " Beat Detector Usage:" << std::endl;
- std::cout << " ./beat_detector [buffer_size] [options]" << std::endl;
- std::cout << "\nOptions:" << std::endl;
- std::cout << " --no-log Disable logging to file" << std::endl;
- std::cout << " --no-stats Disable performance statistics" << std::endl;
- std::cout << " --pitch Enable pitch detection" << std::endl;
- std::cout << " --no-visual Disable visual feedback" << std::endl;
- std::cout << " --help Show this help" << std::endl;
- std::cout << "\nExamples:" << std::endl;
- std::cout << " ./beat_detector # Default settings" << std::endl;
- std::cout << " ./beat_detector 256 --pitch # Smaller buffer with pitch detection" << std::endl;
- std::cout << " ./beat_detector 1024 --no-visual # Larger buffer, no visual feedback" << std::endl;
-}
-
-int main(int argc, char* argv[]) {
- // Parse command line arguments
- uint32_t buffer_size = 512;
- bool enable_logging = true;
- bool enable_performance_stats = true;
- bool enable_pitch_detection = false;
- bool enable_visual_feedback = true;
-
- for (int i = 1; i < argc; ++i) {
- std::string arg = argv[i];
-
- if (arg == "--help" || arg == "-h") {
- print_usage();
- return 0;
- } else if (arg == "--no-log") {
- enable_logging = false;
- } else if (arg == "--no-stats") {
- enable_performance_stats = false;
- } else if (arg == "--pitch") {
- enable_pitch_detection = true;
- } else if (arg == "--no-visual") {
- enable_visual_feedback = false;
- } else if (arg[0] != '-') {
- // Assume it's a buffer size
- try {
- buffer_size = std::stoul(arg);
- if (buffer_size < 64 || buffer_size > 8192) {
- std::cerr << " Buffer size must be between 64 and 8192" << std::endl;
- return 1;
- }
- } catch (...) {
- std::cerr << " Invalid buffer size: " << arg << std::endl;
- return 1;
- }
- } else {
- std::cerr << " Unknown option: " << arg << std::endl;
- print_usage();
- return 1;
- }
- }
-
- // Set up signal handling
- std::signal(SIGINT, EnhancedBeatDetector::signal_handler);
- std::signal(SIGTERM, EnhancedBeatDetector::signal_handler);
-
- try {
- EnhancedBeatDetector detector(buffer_size, enable_logging, enable_performance_stats,
- enable_pitch_detection, enable_visual_feedback);
- detector.run();
- } catch (const std::exception& e) {
- std::cerr << " Error: " << e.what() << std::endl;
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Compilation command:
- * g++ -std=c++17 -O3 -Wall -Wextra -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -I/usr/include/aubio \
- * -o beat_detector beat_detector.cpp -lpipewire-0.3 -laubio -pthread
- */
diff --git a/dots/quickshell/assets/bongocat.gif b/dots/quickshell/assets/bongocat.gif
deleted file mode 100644
index 4a50ff1..0000000
Binary files a/dots/quickshell/assets/bongocat.gif and /dev/null differ
diff --git a/dots/quickshell/assets/kurukuru.gif b/dots/quickshell/assets/kurukuru.gif
deleted file mode 100644
index 38d203d..0000000
Binary files a/dots/quickshell/assets/kurukuru.gif and /dev/null differ
diff --git a/dots/quickshell/config/Appearance.qml b/dots/quickshell/config/Appearance.qml
deleted file mode 100644
index 1751228..0000000
--- a/dots/quickshell/config/Appearance.qml
+++ /dev/null
@@ -1,84 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property Rounding rounding: Rounding {}
- readonly property Spacing spacing: Spacing {}
- readonly property Padding padding: Padding {}
- readonly property Font font: Font {}
- readonly property Anim anim: Anim {}
-
- component Rounding: QtObject {
- readonly property int small: 12
- readonly property int normal: 17
- readonly property int large: 25
- readonly property int full: 1000
- }
-
- component Spacing: QtObject {
- readonly property int small: 7
- readonly property int smaller: 10
- readonly property int normal: 12
- readonly property int larger: 15
- readonly property int large: 20
- }
-
- component Padding: QtObject {
- readonly property int small: 5
- readonly property int smaller: 7
- readonly property int normal: 10
- readonly property int larger: 12
- readonly property int large: 15
- }
-
- component FontFamily: QtObject {
- readonly property string sans: "IBM Plex Sans"
- readonly property string mono: "JetBrains Mono NF"
- readonly property string material: "Material Symbols Rounded"
- }
-
- component FontSize: QtObject {
- readonly property int small: 11
- readonly property int smaller: 12
- readonly property int normal: 13
- readonly property int larger: 15
- readonly property int large: 18
- readonly property int extraLarge: 28
- }
-
- component Font: QtObject {
- readonly property FontFamily family: FontFamily {}
- readonly property FontSize size: FontSize {}
- }
-
- component AnimCurves: QtObject {
- readonly property list emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
- readonly property list emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
- readonly property list emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
- readonly property list standard: [0.2, 0, 0, 1, 1, 1]
- readonly property list standardAccel: [0.3, 0, 1, 1, 1, 1]
- readonly property list standardDecel: [0, 0, 0, 1, 1, 1]
- readonly property list expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]
- readonly property list expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1]
- readonly property list expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1]
- }
-
- component AnimDurations: QtObject {
- readonly property int small: 200
- readonly property int normal: 400
- readonly property int large: 600
- readonly property int extraLarge: 1000
- readonly property int expressiveFastSpatial: 350
- readonly property int expressiveDefaultSpatial: 500
- readonly property int expressiveEffects: 200
- }
-
- component Anim: QtObject {
- readonly property AnimCurves curves: AnimCurves {}
- readonly property AnimDurations durations: AnimDurations {}
- }
-}
diff --git a/dots/quickshell/config/BarConfig.qml b/dots/quickshell/config/BarConfig.qml
deleted file mode 100644
index 46af17a..0000000
--- a/dots/quickshell/config/BarConfig.qml
+++ /dev/null
@@ -1,22 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property JsonObject sizes: JsonObject {
- property int innerHeight: 30
- property int windowPreviewSize: 400
- property int trayMenuWidth: 300
- property int batteryWidth: 300
- }
-
- property JsonObject workspaces: JsonObject {
- property int shown: 5
- property bool rounded: true
- property bool activeIndicator: true
- property bool occupiedBg: false
- property bool showWindows: true
- property bool activeTrail: false
- property string label: " "
- property string occupiedLabel: " "
- property string activeLabel: " "
- }
-}
diff --git a/dots/quickshell/config/BorderConfig.qml b/dots/quickshell/config/BorderConfig.qml
deleted file mode 100644
index 7e95054..0000000
--- a/dots/quickshell/config/BorderConfig.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import "root:/services"
-import Quickshell.Io
-import QtQuick
-
-JsonObject {
- property color colour: Colours.palette.m3surface
- property int thickness: Appearance.padding.normal
- property int rounding: Appearance.rounding.large
-}
diff --git a/dots/quickshell/config/Config.qml b/dots/quickshell/config/Config.qml
deleted file mode 100644
index 2e1e48b..0000000
--- a/dots/quickshell/config/Config.qml
+++ /dev/null
@@ -1,36 +0,0 @@
-pragma Singleton
-
-import "root:/utils"
-import Quickshell
-import Quickshell.Io
-
-Singleton {
- id: root
-
- property alias bar: adapter.bar
- property alias border: adapter.border
- property alias dashboard: adapter.dashboard
- property alias launcher: adapter.launcher
- property alias notifs: adapter.notifs
- property alias osd: adapter.osd
- property alias session: adapter.session
-
- FileView {
- path: `${Paths.config}/shell.json`
- watchChanges: true
- onFileChanged: reload()
- onAdapterUpdated: writeAdapter()
-
- JsonAdapter {
- id: adapter
-
- property JsonObject bar: BarConfig {}
- property JsonObject border: BorderConfig {}
- property JsonObject dashboard: DashboardConfig {}
- property JsonObject launcher: LauncherConfig {}
- property JsonObject notifs: NotifsConfig {}
- property JsonObject osd: OsdConfig {}
- property JsonObject session: SessionConfig {}
- }
- }
-}
diff --git a/dots/quickshell/config/DashboardConfig.qml b/dots/quickshell/config/DashboardConfig.qml
deleted file mode 100644
index 02f838e..0000000
--- a/dots/quickshell/config/DashboardConfig.qml
+++ /dev/null
@@ -1,23 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property int mediaUpdateInterval: 500
- property int visualiserBars: 45
- property string weatherLocation: "" // A lat,long pair, e.g. "37.8267,-122.4233"
-
- property JsonObject sizes: JsonObject {
- readonly property int tabIndicatorHeight: 3
- readonly property int tabIndicatorSpacing: 5
- readonly property int infoWidth: 200
- readonly property int infoIconSize: 25
- readonly property int dateTimeWidth: 110
- readonly property int mediaWidth: 200
- readonly property int mediaProgressSweep: 180
- readonly property int mediaProgressThickness: 8
- readonly property int resourceProgessThickness: 10
- readonly property int weatherWidth: 250
- readonly property int mediaCoverArtSize: 150
- readonly property int mediaVisualiserSize: 80
- readonly property int resourceSize: 200
- }
-}
diff --git a/dots/quickshell/config/LauncherConfig.qml b/dots/quickshell/config/LauncherConfig.qml
deleted file mode 100644
index ea3c364..0000000
--- a/dots/quickshell/config/LauncherConfig.qml
+++ /dev/null
@@ -1,15 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property int maxShown: 8
- property int maxWallpapers: 9 // Warning: even numbers look bad
- property string actionPrefix: ">"
- property bool enableDangerousActions: false // Allow actions that can cause losing data, like shutdown, reboot and logout
-
- property JsonObject sizes: JsonObject {
- property int itemWidth: 600
- property int itemHeight: 57
- property int wallpaperWidth: 280
- property int wallpaperHeight: 200
- }
-}
diff --git a/dots/quickshell/config/NotifsConfig.qml b/dots/quickshell/config/NotifsConfig.qml
deleted file mode 100644
index fdf070d..0000000
--- a/dots/quickshell/config/NotifsConfig.qml
+++ /dev/null
@@ -1,15 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property bool expire: true
- property int defaultExpireTimeout: 3000
- property real clearThreshold: 0.3
- property int expandThreshold: 20
- property bool actionOnClick: false
-
- property JsonObject sizes: JsonObject {
- property int width: 400
- property int image: 41
- property int badge: 20
- }
-}
diff --git a/dots/quickshell/config/OsdConfig.qml b/dots/quickshell/config/OsdConfig.qml
deleted file mode 100644
index 7275e22..0000000
--- a/dots/quickshell/config/OsdConfig.qml
+++ /dev/null
@@ -1,10 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property int hideDelay: 2000
-
- property JsonObject sizes: JsonObject {
- property int sliderWidth: 30
- property int sliderHeight: 150
- }
-}
diff --git a/dots/quickshell/config/SessionConfig.qml b/dots/quickshell/config/SessionConfig.qml
deleted file mode 100644
index 0915469..0000000
--- a/dots/quickshell/config/SessionConfig.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property int dragThreshold: 30
-
- property JsonObject sizes: JsonObject {
- property int button: 80
- }
-}
diff --git a/dots/quickshell/modules/Shortcuts.qml b/dots/quickshell/modules/Shortcuts.qml
deleted file mode 100644
index 3d665ff..0000000
--- a/dots/quickshell/modules/Shortcuts.qml
+++ /dev/null
@@ -1,65 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import Quickshell
-import Quickshell.Io
-
-Scope {
- id: root
-
- property bool launcherInterrupted
-
- CustomShortcut {
- name: "showall"
- description: "Toggle launcher, dashboard and osd"
- onPressed: {
- const v = Visibilities.getForActive();
- v.launcher = v.dashboard = v.osd = !(v.launcher || v.dashboard || v.osd);
- }
- }
-
- CustomShortcut {
- name: "session"
- description: "Toggle session menu"
- onPressed: {
- const visibilities = Visibilities.getForActive();
- visibilities.session = !visibilities.session;
- }
- }
-
- CustomShortcut {
- name: "launcher"
- description: "Toggle launcher"
- onPressed: root.launcherInterrupted = false
- onReleased: {
- if (!root.launcherInterrupted) {
- const visibilities = Visibilities.getForActive();
- visibilities.launcher = !visibilities.launcher;
- }
- root.launcherInterrupted = false;
- }
- }
-
- CustomShortcut {
- name: "launcherInterrupt"
- description: "Interrupt launcher keybind"
- onPressed: root.launcherInterrupted = true
- }
-
- IpcHandler {
- target: "drawers"
-
- function toggle(drawer: string): void {
- if (list().split("\n").includes(drawer)) {
- const visibilities = Visibilities.getForActive();
- visibilities[drawer] = !visibilities[drawer];
- } else {
- console.warn(`[IPC] Drawer "${drawer}" does not exist`);
- }
- }
-
- function list(): string {
- const visibilities = Visibilities.getForActive();
- return Object.keys(visibilities).filter(k => typeof visibilities[k] === "boolean").join("\n");
- }
- }
-}
diff --git a/dots/quickshell/modules/background/Background.qml b/dots/quickshell/modules/background/Background.qml
deleted file mode 100644
index 11c9151..0000000
--- a/dots/quickshell/modules/background/Background.qml
+++ /dev/null
@@ -1,26 +0,0 @@
-import "root:/widgets"
-import Quickshell
-import Quickshell.Wayland
-
-Variants {
- model: Quickshell.screens
-
- StyledWindow {
- id: win
-
- required property ShellScreen modelData
-
- screen: modelData
- name: "background"
- WlrLayershell.exclusionMode: ExclusionMode.Ignore
- WlrLayershell.layer: WlrLayer.Background
- color: "black"
-
- anchors.top: true
- anchors.bottom: true
- anchors.left: true
- anchors.right: true
-
- Wallpaper {}
- }
-}
diff --git a/dots/quickshell/modules/background/Wallpaper.qml b/dots/quickshell/modules/background/Wallpaper.qml
deleted file mode 100644
index f4e3243..0000000
--- a/dots/quickshell/modules/background/Wallpaper.qml
+++ /dev/null
@@ -1,71 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Item {
- id: root
-
- property string source: Wallpapers.current
- property Image current: one
-
- anchors.fill: parent
-
- onSourceChanged: {
- if (current === one)
- two.update();
- else
- one.update();
- }
-
- Img {
- id: one
- }
-
- Img {
- id: two
- }
-
- component Img: CachingImage {
- id: img
-
- function update(): void {
- if (path === root.source)
- root.current = this;
- else
- path = root.source;
- }
-
- anchors.fill: parent
-
- opacity: 0
- scale: Wallpapers.showPreview ? 1 : 0.8
-
- onStatusChanged: {
- if (status === Image.Ready)
- root.current = this;
- }
-
- states: State {
- name: "visible"
- when: root.current === img
-
- PropertyChanges {
- img.opacity: 1
- img.scale: 1
- }
- }
-
- transitions: Transition {
- NumberAnimation {
- target: img
- properties: "opacity,scale"
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/Bar.qml b/dots/quickshell/modules/bar/Bar.qml
deleted file mode 100644
index 1d0db8d..0000000
--- a/dots/quickshell/modules/bar/Bar.qml
+++ /dev/null
@@ -1,174 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import "root:/modules/bar/popouts" as BarPopouts
-import "components"
-import "components/workspaces"
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property BarPopouts.Wrapper popouts
-
- function checkPopout(y: real): void {
- const spacing = Appearance.spacing.small;
- const aw = activeWindow.child;
- const awy = activeWindow.y + aw.y;
-
- const ty = tray.y;
- const th = tray.implicitHeight;
- const trayItems = tray.items;
-
- const n = statusIconsInner.network;
- const ny = statusIcons.y + statusIconsInner.y + n.y - spacing / 2;
-
- const bls = statusIcons.y + statusIconsInner.y + statusIconsInner.bs - spacing / 2;
- const ble = statusIcons.y + statusIconsInner.y + statusIconsInner.be + spacing / 2;
-
- const b = statusIconsInner.battery;
- const by = statusIcons.y + statusIconsInner.y + b.y - spacing / 2;
-
- if (y >= awy && y <= awy + aw.implicitHeight) {
- popouts.currentName = "activewindow";
- popouts.currentCenter = Qt.binding(() => activeWindow.y + aw.y + aw.implicitHeight / 2);
- popouts.hasCurrent = true;
- } else if (y > ty && y < ty + th) {
- const index = Math.floor(((y - ty) / th) * trayItems.count);
- const item = trayItems.itemAt(index);
-
- popouts.currentName = `traymenu${index}`;
- popouts.currentCenter = Qt.binding(() => tray.y + item.y + item.implicitHeight / 2);
- popouts.hasCurrent = true;
- } else if (y >= ny && y <= ny + n.implicitHeight + spacing) {
- popouts.currentName = "network";
- popouts.currentCenter = Qt.binding(() => statusIcons.y + statusIconsInner.y + n.y + n.implicitHeight / 2);
- popouts.hasCurrent = true;
- } else if (y >= bls && y <= ble) {
- popouts.currentName = "bluetooth";
- popouts.currentCenter = Qt.binding(() => statusIcons.y + statusIconsInner.y + statusIconsInner.bs + (statusIconsInner.be - statusIconsInner.bs) / 2);
- popouts.hasCurrent = true;
- } else if (y >= by && y <= by + b.implicitHeight + spacing) {
- popouts.currentName = "battery";
- popouts.currentCenter = Qt.binding(() => statusIcons.y + statusIconsInner.y + b.y + b.implicitHeight / 2);
- popouts.hasCurrent = true;
- } else {
- popouts.hasCurrent = false;
- }
- }
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.left: parent.left
-
- implicitWidth: child.implicitWidth + Config.border.thickness * 2
-
- Item {
- id: child
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
-
- implicitWidth: Math.max(osIcon.implicitWidth, workspaces.implicitWidth, activeWindow.implicitWidth, tray.implicitWidth, clock.implicitWidth, statusIcons.implicitWidth, power.implicitWidth)
-
- OsIcon {
- id: osIcon
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- anchors.topMargin: Appearance.padding.large
- }
-
- StyledRect {
- id: workspaces
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: osIcon.bottom
- anchors.topMargin: Appearance.spacing.normal
-
- radius: Appearance.rounding.full
- color: Colours.palette.m3surfaceContainer
-
- implicitWidth: workspacesInner.implicitWidth + Appearance.padding.small * 2
- implicitHeight: workspacesInner.implicitHeight + Appearance.padding.small * 2
-
- MouseArea {
- anchors.fill: parent
- anchors.leftMargin: -Config.border.thickness
- anchors.rightMargin: -Config.border.thickness
-
- onWheel: event => {
- const activeWs = Hyprland.activeClient?.workspace?.name;
- if (activeWs?.startsWith("special:"))
- Hyprland.dispatch(`togglespecialworkspace ${activeWs.slice(8)}`);
- else if (event.angleDelta.y < 0 || Hyprland.activeWsId > 1)
- Hyprland.dispatch(`workspace r${event.angleDelta.y > 0 ? "-" : "+"}1`);
- }
- }
-
- Workspaces {
- id: workspacesInner
-
- anchors.centerIn: parent
- }
- }
-
- ActiveWindow {
- id: activeWindow
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: workspaces.bottom
- anchors.bottom: tray.top
- anchors.margins: Appearance.spacing.large
-
- monitor: Brightness.getMonitorForScreen(root.screen)
- }
-
- Tray {
- id: tray
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: clock.top
- anchors.bottomMargin: Appearance.spacing.larger
- }
-
- Clock {
- id: clock
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: statusIcons.top
- anchors.bottomMargin: Appearance.spacing.normal
- }
-
- StyledRect {
- id: statusIcons
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: power.top
- anchors.bottomMargin: Appearance.spacing.normal
-
- radius: Appearance.rounding.full
- color: Colours.palette.m3surfaceContainer
-
- implicitHeight: statusIconsInner.implicitHeight + Appearance.padding.normal * 2
-
- StatusIcons {
- id: statusIconsInner
-
- anchors.centerIn: parent
- }
- }
-
- Power {
- id: power
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- anchors.bottomMargin: Appearance.padding.large
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/components/ActiveWindow.qml b/dots/quickshell/modules/bar/components/ActiveWindow.qml
deleted file mode 100644
index f6204ae..0000000
--- a/dots/quickshell/modules/bar/components/ActiveWindow.qml
+++ /dev/null
@@ -1,140 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/utils"
-import "root:/config"
-import QtQuick
-
-Item {
- id: root
-
- required property Brightness.Monitor monitor
- property color colour: Colours.palette.m3primary
- readonly property Item child: child
-
- implicitWidth: child.implicitWidth
- implicitHeight: child.implicitHeight
-
- MouseArea {
- anchors.top: parent.top
- anchors.bottom: child.top
- anchors.left: parent.left
- anchors.right: parent.right
-
- onWheel: event => {
- if (event.angleDelta.y > 0)
- Audio.setVolume(Audio.volume + 0.1);
- else if (event.angleDelta.y < 0)
- Audio.setVolume(Audio.volume - 0.1);
- }
- }
-
- MouseArea {
- anchors.top: child.bottom
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.right: parent.right
-
- onWheel: event => {
- const monitor = root.monitor;
- if (event.angleDelta.y > 0)
- monitor.setBrightness(monitor.brightness + 0.1);
- else if (event.angleDelta.y < 0)
- monitor.setBrightness(monitor.brightness - 0.1);
- }
- }
-
- Item {
- id: child
-
- property Item current: text1
-
- anchors.centerIn: parent
-
- clip: true
- implicitWidth: Math.max(icon.implicitWidth, current.implicitHeight)
- implicitHeight: icon.implicitHeight + current.implicitWidth + current.anchors.topMargin
-
- MaterialIcon {
- id: icon
-
- animate: true
- text: Icons.getAppCategoryIcon(Hyprland.activeClient?.wmClass, "desktop_windows")
- color: root.colour
-
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- Title {
- id: text1
- }
-
- Title {
- id: text2
- }
-
- TextMetrics {
- id: metrics
-
- text: Hyprland.activeClient?.title ?? qsTr("Desktop")
- font.pointSize: Appearance.font.size.smaller
- font.family: Appearance.font.family.mono
- elide: Qt.ElideRight
- elideWidth: root.height - icon.height
-
- onTextChanged: {
- const next = child.current === text1 ? text2 : text1;
- next.text = elidedText;
- child.current = next;
- }
- onElideWidthChanged: child.current.text = elidedText
- }
-
- Behavior on implicitWidth {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- component Title: StyledText {
- id: text
-
- anchors.horizontalCenter: icon.horizontalCenter
- anchors.top: icon.bottom
- anchors.topMargin: Appearance.spacing.small
-
- font.pointSize: metrics.font.pointSize
- font.family: metrics.font.family
- color: root.colour
- opacity: child.current === this ? 1 : 0
-
- transform: Rotation {
- angle: 90
- origin.x: text.implicitHeight / 2
- origin.y: text.implicitHeight / 2
- }
-
- width: implicitHeight
- height: implicitWidth
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/components/Clock.qml b/dots/quickshell/modules/bar/components/Clock.qml
deleted file mode 100644
index ea57e2b..0000000
--- a/dots/quickshell/modules/bar/components/Clock.qml
+++ /dev/null
@@ -1,33 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Column {
- id: root
-
- property color colour: Colours.palette.m3tertiary
-
- spacing: Appearance.spacing.small
-
- MaterialIcon {
- id: icon
-
- text: "calendar_month"
- color: root.colour
-
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- StyledText {
- id: text
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- horizontalAlignment: StyledText.AlignHCenter
- text: Time.format("hh\nmm")
- font.pointSize: Appearance.font.size.smaller
- font.family: Appearance.font.family.mono
- color: root.colour
- }
-}
diff --git a/dots/quickshell/modules/bar/components/OsIcon.qml b/dots/quickshell/modules/bar/components/OsIcon.qml
deleted file mode 100644
index e040cf0..0000000
--- a/dots/quickshell/modules/bar/components/OsIcon.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/utils"
-import "root:/config"
-
-StyledText {
- text: Icons.osIcon
- font.pointSize: Appearance.font.size.smaller
- font.family: Appearance.font.family.mono
- color: Colours.palette.m3tertiary
-}
diff --git a/dots/quickshell/modules/bar/components/Power.qml b/dots/quickshell/modules/bar/components/Power.qml
deleted file mode 100644
index a870cb3..0000000
--- a/dots/quickshell/modules/bar/components/Power.qml
+++ /dev/null
@@ -1,27 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-
-MaterialIcon {
- text: "power_settings_new"
- color: Colours.palette.m3error
- font.bold: true
- font.pointSize: Appearance.font.size.normal
-
- StateLayer {
- anchors.fill: undefined
- anchors.centerIn: parent
- anchors.horizontalCenterOffset: 1
-
- implicitWidth: parent.implicitHeight + Appearance.padding.small * 2
- implicitHeight: implicitWidth
-
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- const v = Visibilities.screens[QsWindow.window.screen];
- v.session = !v.session;
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/components/StatusIcons.qml b/dots/quickshell/modules/bar/components/StatusIcons.qml
deleted file mode 100644
index f92159b..0000000
--- a/dots/quickshell/modules/bar/components/StatusIcons.qml
+++ /dev/null
@@ -1,114 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/utils"
-import "root:/config"
-import Quickshell
-import Quickshell.Services.UPower
-import QtQuick
-
-Item {
- id: root
-
- property color colour: Colours.palette.m3secondary
-
- readonly property Item network: network
- readonly property real bs: bluetooth.y
- readonly property real be: repeater.count > 0 ? devices.y + devices.implicitHeight : bluetooth.y + bluetooth.implicitHeight
- readonly property Item battery: battery
-
- clip: true
- implicitWidth: Math.max(network.implicitWidth, bluetooth.implicitWidth, devices.implicitWidth, battery.implicitWidth)
- implicitHeight: network.implicitHeight + bluetooth.implicitHeight + bluetooth.anchors.topMargin + (repeater.count > 0 ? devices.implicitHeight + devices.anchors.topMargin : 0) + battery.implicitHeight + battery.anchors.topMargin
-
- MaterialIcon {
- id: network
-
- animate: true
- text: Network.active ? Icons.getNetworkIcon(Network.active.strength ?? 0) : "wifi_off"
- color: root.colour
-
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- MaterialIcon {
- id: bluetooth
-
- anchors.horizontalCenter: network.horizontalCenter
- anchors.top: network.bottom
- anchors.topMargin: Appearance.spacing.small
-
- animate: true
- text: Bluetooth.powered ? "bluetooth" : "bluetooth_disabled"
- color: root.colour
- }
-
- Column {
- id: devices
-
- anchors.horizontalCenter: bluetooth.horizontalCenter
- anchors.top: bluetooth.bottom
- anchors.topMargin: Appearance.spacing.small
-
- Repeater {
- id: repeater
-
- model: ScriptModel {
- values: Bluetooth.devices.filter(d => d.connected)
- }
-
- MaterialIcon {
- required property Bluetooth.Device modelData
-
- animate: true
- text: Icons.getBluetoothIcon(modelData.icon)
- color: root.colour
- }
- }
- }
-
- MaterialIcon {
- id: battery
-
- anchors.horizontalCenter: devices.horizontalCenter
- anchors.top: repeater.count > 0 ? devices.bottom : bluetooth.bottom
- anchors.topMargin: Appearance.spacing.small
-
- animate: true
- text: {
- if (!UPower.displayDevice.isLaptopBattery) {
- if (PowerProfiles.profile === PowerProfile.PowerSaver)
- return "energy_savings_leaf";
- if (PowerProfiles.profile === PowerProfile.Performance)
- return "rocket_launch";
- return "balance";
- }
-
- const perc = UPower.displayDevice.percentage;
- const charging = !UPower.onBattery;
- if (perc === 1)
- return charging ? "battery_charging_full" : "battery_full";
- let level = Math.floor(perc * 7);
- if (charging && (level === 4 || level === 1))
- level--;
- return charging ? `battery_charging_${(level + 3) * 10}` : `battery_${level}_bar`;
- }
- color: !UPower.onBattery || UPower.displayDevice.percentage > 0.2 ? root.colour : Colours.palette.m3error
- fill: 1
- }
-
- Behavior on implicitWidth {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/components/Tray.qml b/dots/quickshell/modules/bar/components/Tray.qml
deleted file mode 100644
index 6280a30..0000000
--- a/dots/quickshell/modules/bar/components/Tray.qml
+++ /dev/null
@@ -1,56 +0,0 @@
-import "root:/config"
-import Quickshell.Services.SystemTray
-import QtQuick
-
-Item {
- id: root
-
- readonly property Repeater items: items
-
- clip: true
- visible: width > 0 && height > 0 // To avoid warnings about being visible with no size
-
- implicitWidth: layout.implicitWidth
- implicitHeight: layout.implicitHeight
-
- Column {
- id: layout
-
- spacing: Appearance.spacing.small
-
- add: Transition {
- NumberAnimation {
- properties: "scale"
- from: 0
- to: 1
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- Repeater {
- id: items
-
- model: SystemTray.items
-
- TrayItem {}
- }
- }
-
- Behavior on implicitWidth {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/components/TrayItem.qml b/dots/quickshell/modules/bar/components/TrayItem.qml
deleted file mode 100644
index b8e5d42..0000000
--- a/dots/quickshell/modules/bar/components/TrayItem.qml
+++ /dev/null
@@ -1,48 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import Quickshell.Services.SystemTray
-import QtQuick
-
-MouseArea {
- id: root
-
- required property SystemTrayItem modelData
-
- acceptedButtons: Qt.LeftButton | Qt.RightButton
- implicitWidth: Appearance.font.size.small * 2
- implicitHeight: Appearance.font.size.small * 2
-
- onClicked: event => {
- if (event.button === Qt.LeftButton)
- modelData.activate();
- else if (modelData.hasMenu)
- menu.open();
- }
-
- // TODO custom menu
- QsMenuAnchor {
- id: menu
-
- menu: root.modelData.menu
- anchor.window: this.QsWindow.window
- }
-
- IconImage {
- id: icon
-
- source: {
- let icon = root.modelData.icon;
- if (icon.includes("?path=")) {
- const [name, path] = icon.split("?path=");
- icon = `file://${path}/${name.slice(name.lastIndexOf("/") + 1)}`;
- }
- return icon;
- }
- asynchronous: true
- anchors.fill: parent
- }
-}
diff --git a/dots/quickshell/modules/bar/components/workspaces/ActiveIndicator.qml b/dots/quickshell/modules/bar/components/workspaces/ActiveIndicator.qml
deleted file mode 100644
index 6807397..0000000
--- a/dots/quickshell/modules/bar/components/workspaces/ActiveIndicator.qml
+++ /dev/null
@@ -1,111 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Effects
-
-StyledRect {
- id: root
-
- required property list workspaces
- required property Item mask
- required property real maskWidth
- required property real maskHeight
- required property int groupOffset
-
- readonly property int currentWsIdx: Hyprland.activeWsId - 1 - groupOffset
- property real leading: getWsY(currentWsIdx)
- property real trailing: getWsY(currentWsIdx)
- property real currentSize: workspaces[currentWsIdx]?.size ?? 0
- property real offset: Math.min(leading, trailing)
- property real size: {
- const s = Math.abs(leading - trailing) + currentSize;
- if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx)
- return Math.min(getWsY(lastWs) + (workspaces[lastWs]?.size ?? 0) - offset, s);
- return s;
- }
-
- property int cWs
- property int lastWs
-
- function getWsY(idx: int): real {
- let y = 0;
- for (let i = 0; i < idx; i++)
- y += workspaces[i]?.size ?? 0;
- return y;
- }
-
- onCurrentWsIdxChanged: {
- lastWs = cWs;
- cWs = currentWsIdx;
- }
-
- clip: true
- x: 1
- y: offset + 1
- implicitWidth: Config.bar.sizes.innerHeight - 2
- implicitHeight: size - 2
- radius: Config.bar.workspaces.rounded ? Appearance.rounding.full : 0
- color: Colours.palette.m3primary
-
- StyledRect {
- id: base
-
- visible: false
- anchors.fill: parent
- color: Colours.palette.m3onPrimary
- }
-
- MultiEffect {
- source: base
- maskSource: root.mask
- maskEnabled: true
- maskSpreadAtMin: 1
- maskThresholdMin: 0.5
-
- x: 0
- y: -parent.offset
- implicitWidth: root.maskWidth
- implicitHeight: root.maskHeight
-
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- Behavior on leading {
- enabled: Config.bar.workspaces.activeTrail
-
- Anim {}
- }
-
- Behavior on trailing {
- enabled: Config.bar.workspaces.activeTrail
-
- Anim {
- duration: Appearance.anim.durations.normal * 2
- }
- }
-
- Behavior on currentSize {
- enabled: Config.bar.workspaces.activeTrail
-
- Anim {}
- }
-
- Behavior on offset {
- enabled: !Config.bar.workspaces.activeTrail
-
- Anim {}
- }
-
- Behavior on size {
- enabled: !Config.bar.workspaces.activeTrail
-
- Anim {}
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
-}
diff --git a/dots/quickshell/modules/bar/components/workspaces/OccupiedBg.qml b/dots/quickshell/modules/bar/components/workspaces/OccupiedBg.qml
deleted file mode 100644
index c5ed7cc..0000000
--- a/dots/quickshell/modules/bar/components/workspaces/OccupiedBg.qml
+++ /dev/null
@@ -1,99 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property list workspaces
- required property var occupied
- required property int groupOffset
-
- property list pills: []
-
- onOccupiedChanged: {
- let count = 0;
- const start = groupOffset;
- const end = start + Config.bar.workspaces.shown;
- for (const [ws, occ] of Object.entries(occupied)) {
- if (ws > start && ws <= end && occ) {
- if (!occupied[ws - 1]) {
- if (pills[count])
- pills[count].start = ws;
- else
- pills.push(pillComp.createObject(root, {
- start: ws
- }));
- count++;
- }
- if (!occupied[ws + 1])
- pills[count - 1].end = ws;
- }
- }
- if (pills.length > count)
- pills.splice(count, pills.length - count).forEach(p => p.destroy());
- }
-
- Repeater {
- model: ScriptModel {
- values: root.pills.filter(p => p)
- }
-
- StyledRect {
- id: rect
-
- required property var modelData
-
- readonly property Workspace start: root.workspaces[modelData.start - 1 - root.groupOffset] ?? null
- readonly property Workspace end: root.workspaces[modelData.end - 1 - root.groupOffset] ?? null
-
- color: Colours.alpha(Colours.palette.m3surfaceContainerHigh, true)
- radius: Config.bar.workspaces.rounded ? Appearance.rounding.full : 0
-
- x: start?.x ?? 0
- y: start?.y ?? 0
- implicitWidth: Config.bar.sizes.innerHeight
- implicitHeight: end?.y + end?.height - start?.y
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- scale: 0
- Component.onCompleted: scale = 1
-
- Behavior on scale {
- Anim {
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- Behavior on x {
- Anim {}
- }
-
- Behavior on y {
- Anim {}
- }
- }
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
-
- component Pill: QtObject {
- property int start
- property int end
- }
-
- Component {
- id: pillComp
-
- Pill {}
- }
-}
diff --git a/dots/quickshell/modules/bar/components/workspaces/Workspace.qml b/dots/quickshell/modules/bar/components/workspaces/Workspace.qml
deleted file mode 100644
index 6cf5c40..0000000
--- a/dots/quickshell/modules/bar/components/workspaces/Workspace.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/utils"
-import "root:/config"
-import Quickshell
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property int index
- required property var occupied
- required property int groupOffset
-
- readonly property bool isWorkspace: true // Flag for finding workspace children
- // Unanimated prop for others to use as reference
- readonly property real size: childrenRect.height + (hasWindows ? Appearance.padding.normal : 0)
-
- readonly property int ws: groupOffset + index + 1
- readonly property bool isOccupied: occupied[ws] ?? false
- readonly property bool hasWindows: isOccupied && Config.bar.workspaces.showWindows
-
- Layout.preferredWidth: childrenRect.width
- Layout.preferredHeight: size
-
- StyledText {
- id: indicator
-
- readonly property string label: Config.bar.workspaces.label || root.ws
- readonly property string occupiedLabel: Config.bar.workspaces.occupiedLabel || label
- readonly property string activeLabel: Config.bar.workspaces.activeLabel || (root.isOccupied ? occupiedLabel : label)
-
- animate: true
- text: Hyprland.activeWsId === root.ws ? activeLabel : root.isOccupied ? occupiedLabel : label
- color: Config.bar.workspaces.occupiedBg || root.isOccupied || Hyprland.activeWsId === root.ws ? Colours.palette.m3onSurface : Colours.palette.m3outlineVariant
- horizontalAlignment: StyledText.AlignHCenter
- verticalAlignment: StyledText.AlignVCenter
-
- width: Config.bar.sizes.innerHeight
- height: Config.bar.sizes.innerHeight
- }
-
- Loader {
- id: windows
-
- active: Config.bar.workspaces.showWindows
- asynchronous: true
-
- anchors.horizontalCenter: indicator.horizontalCenter
- anchors.top: indicator.bottom
-
- sourceComponent: Column {
- spacing: Appearance.spacing.small
-
- add: Transition {
- Anim {
- properties: "scale"
- from: 0
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- Repeater {
- model: ScriptModel {
- values: Hyprland.clients.filter(c => c.workspace?.id === root.ws)
- }
-
- MaterialIcon {
- required property Hyprland.Client modelData
-
- text: Icons.getAppCategoryIcon(modelData.wmClass, "terminal")
- color: Colours.palette.m3onSurfaceVariant
- }
- }
- }
- }
-
- Behavior on Layout.preferredWidth {
- Anim {}
- }
-
- Behavior on Layout.preferredHeight {
- Anim {}
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
-}
diff --git a/dots/quickshell/modules/bar/components/workspaces/Workspaces.qml b/dots/quickshell/modules/bar/components/workspaces/Workspaces.qml
deleted file mode 100644
index 9264762..0000000
--- a/dots/quickshell/modules/bar/components/workspaces/Workspaces.qml
+++ /dev/null
@@ -1,75 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- readonly property list workspaces: layout.children.filter(c => c.isWorkspace).sort((w1, w2) => w1.ws - w2.ws)
- readonly property var occupied: Hyprland.workspaces.values.reduce((acc, curr) => {
- acc[curr.id] = curr.lastIpcObject.windows > 0;
- return acc;
- }, {})
- readonly property int groupOffset: Math.floor((Hyprland.activeWsId - 1) / Config.bar.workspaces.shown) * Config.bar.workspaces.shown
-
- implicitWidth: layout.implicitWidth
- implicitHeight: layout.implicitHeight
-
- ColumnLayout {
- id: layout
-
- spacing: 0
- layer.enabled: true
- layer.smooth: true
-
- Repeater {
- model: Config.bar.workspaces.shown
-
- Workspace {
- occupied: root.occupied
- groupOffset: root.groupOffset
- }
- }
- }
-
- Loader {
- active: Config.bar.workspaces.occupiedBg
- asynchronous: true
-
- z: -1
- anchors.fill: parent
-
- sourceComponent: OccupiedBg {
- workspaces: root.workspaces
- occupied: root.occupied
- groupOffset: root.groupOffset
- }
- }
-
- Loader {
- active: Config.bar.workspaces.activeIndicator
- asynchronous: true
-
- sourceComponent: ActiveIndicator {
- workspaces: root.workspaces
- mask: layout
- maskWidth: root.width
- maskHeight: root.height
- groupOffset: root.groupOffset
- }
- }
-
- MouseArea {
- anchors.fill: parent
-
- onPressed: event => {
- const ws = layout.childAt(event.x, event.y).index + root.groupOffset + 1;
- if (Hyprland.activeWsId !== ws)
- Hyprland.dispatch(`workspace ${ws}`);
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/ActiveWindow.qml b/dots/quickshell/modules/bar/popouts/ActiveWindow.qml
deleted file mode 100644
index e256792..0000000
--- a/dots/quickshell/modules/bar/popouts/ActiveWindow.qml
+++ /dev/null
@@ -1,75 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/utils"
-import "root:/config"
-import Quickshell.Widgets
-import Quickshell.Wayland
-import QtQuick
-
-Item {
- id: root
-
- implicitWidth: Hyprland.activeClient ? child.implicitWidth : -Appearance.padding.large * 2
- implicitHeight: child.implicitHeight
-
- Column {
- id: child
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.normal
-
- Row {
- id: detailsRow
-
- spacing: Appearance.spacing.normal
-
- IconImage {
- id: icon
-
- implicitSize: details.implicitHeight
- source: Icons.getAppIcon(Hyprland.activeClient?.wmClass ?? "", "image-missing")
- }
-
- Column {
- id: details
-
- StyledText {
- text: Hyprland.activeClient?.title ?? ""
- font.pointSize: Appearance.font.size.normal
-
- elide: Text.ElideRight
- width: preview.implicitWidth - icon.implicitWidth - detailsRow.spacing
- }
-
- StyledText {
- text: Hyprland.activeClient?.wmClass ?? ""
- color: Colours.palette.m3onSurfaceVariant
-
- elide: Text.ElideRight
- width: preview.implicitWidth - icon.implicitWidth - detailsRow.spacing
- }
- }
- }
-
- ClippingWrapperRectangle {
- color: "transparent"
- radius: Appearance.rounding.small
-
- ScreencopyView {
- id: preview
-
- captureSource: Hyprland.activeClient ? ToplevelManager.activeToplevel : null
- live: visible
-
- constraintSize.width: Config.bar.sizes.windowPreviewSize
- constraintSize.height: Config.bar.sizes.windowPreviewSize
- }
- }
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/Background.qml b/dots/quickshell/modules/bar/popouts/Background.qml
deleted file mode 100644
index c099118..0000000
--- a/dots/quickshell/modules/bar/popouts/Background.qml
+++ /dev/null
@@ -1,74 +0,0 @@
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Shapes
-
-ShapePath {
- id: root
-
- required property Wrapper wrapper
- required property bool invertBottomRounding
- readonly property real rounding: Config.border.rounding
- readonly property bool flatten: wrapper.width < rounding * 2
- readonly property real roundingX: flatten ? wrapper.width / 2 : rounding
- property real ibr: invertBottomRounding ? -1 : 1
-
- strokeWidth: -1
- fillColor: Config.border.colour
-
- PathArc {
- relativeX: root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: root.wrapper.width - root.roundingX * 2
- relativeY: 0
- }
- PathArc {
- relativeX: root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- }
- PathLine {
- relativeX: 0
- relativeY: root.wrapper.height - root.rounding * 2
- }
- PathArc {
- relativeX: -root.roundingX * root.ibr
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- direction: root.ibr < 0 ? PathArc.Counterclockwise : PathArc.Clockwise
- }
- PathLine {
- relativeX: -(root.wrapper.width - root.roundingX - root.roundingX * root.ibr)
- relativeY: 0
- }
- PathArc {
- relativeX: -root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- direction: PathArc.Counterclockwise
- }
-
- Behavior on fillColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on ibr {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/Battery.qml b/dots/quickshell/modules/bar/popouts/Battery.qml
deleted file mode 100644
index ebd0fc8..0000000
--- a/dots/quickshell/modules/bar/popouts/Battery.qml
+++ /dev/null
@@ -1,235 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell.Services.UPower
-import QtQuick
-
-Column {
- id: root
-
- spacing: Appearance.spacing.normal
- width: Config.bar.sizes.batteryWidth
-
- StyledText {
- text: UPower.displayDevice.isLaptopBattery ? qsTr("Remaining: %1%").arg(Math.round(UPower.displayDevice.percentage * 100)) : qsTr("No battery detected")
- }
-
- StyledText {
- function formatSeconds(s: int, fallback: string): string {
- const day = Math.floor(s / 86400);
- const hr = Math.floor(s / 3600) % 60;
- const min = Math.floor(s / 60) % 60;
-
- let comps = [];
- if (day > 0)
- comps.push(`${day} days`);
- if (hr > 0)
- comps.push(`${hr} hours`);
- if (min > 0)
- comps.push(`${min} mins`);
-
- return comps.join(", ") || fallback;
- }
-
- text: UPower.displayDevice.isLaptopBattery ? qsTr("Time %1: %2").arg(UPower.onBattery ? "remaining" : "until charged").arg(UPower.onBattery ? formatSeconds(UPower.displayDevice.timeToEmpty, "Calculating...") : formatSeconds(UPower.displayDevice.timeToFull, "Fully charged!")) : qsTr("Power profile: %1").arg(PowerProfile.toString(PowerProfiles.profile))
- }
-
- Loader {
- anchors.horizontalCenter: parent.horizontalCenter
-
- active: PowerProfiles.degradationReason !== PerformanceDegradationReason.None
- asynchronous: true
-
- height: active ? (item?.implicitHeight ?? 0) : 0
-
- sourceComponent: StyledRect {
- implicitWidth: child.implicitWidth + Appearance.padding.normal * 2
- implicitHeight: child.implicitHeight + Appearance.padding.smaller * 2
-
- color: Colours.palette.m3error
- radius: Appearance.rounding.normal
-
- Column {
- id: child
-
- anchors.centerIn: parent
-
- Row {
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Appearance.spacing.small
-
- MaterialIcon {
- anchors.verticalCenter: parent.verticalCenter
- anchors.verticalCenterOffset: -font.pointSize / 10
-
- text: "warning"
- color: Colours.palette.m3onError
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: qsTr("Performance Degraded")
- color: Colours.palette.m3onError
- font.family: Appearance.font.family.mono
- font.weight: 500
- }
-
- MaterialIcon {
- anchors.verticalCenter: parent.verticalCenter
- anchors.verticalCenterOffset: -font.pointSize / 10
-
- text: "warning"
- color: Colours.palette.m3onError
- }
- }
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
-
- text: qsTr("Reason: %1").arg(PerformanceDegradationReason.toString(PowerProfiles.degradationReason))
- color: Colours.palette.m3onError
- }
- }
- }
- }
-
- StyledRect {
- id: profiles
-
- property string current: {
- const p = PowerProfiles.profile;
- if (p === PowerProfile.PowerSaver)
- return saver.icon;
- if (p === PowerProfile.Performance)
- return perf.icon;
- return balance.icon;
- }
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + Appearance.padding.normal * 2 + Appearance.spacing.large * 2
- implicitHeight: Math.max(saver.implicitHeight, balance.implicitHeight, perf.implicitHeight) + Appearance.padding.small * 2
-
- color: Colours.palette.m3surfaceContainer
- radius: Appearance.rounding.full
-
- StyledRect {
- id: indicator
-
- color: Colours.palette.m3primary
- radius: Appearance.rounding.full
- state: profiles.current
-
- states: [
- State {
- name: saver.icon
-
- Fill {
- item: saver
- }
- },
- State {
- name: balance.icon
-
- Fill {
- item: balance
- }
- },
- State {
- name: perf.icon
-
- Fill {
- item: perf
- }
- }
- ]
-
- transitions: Transition {
- AnchorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- Profile {
- id: saver
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: Appearance.padding.small
-
- profile: PowerProfile.PowerSaver
- icon: "energy_savings_leaf"
- }
-
- Profile {
- id: balance
-
- anchors.centerIn: parent
-
- profile: PowerProfile.Balanced
- icon: "balance"
- }
-
- Profile {
- id: perf
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- anchors.rightMargin: Appearance.padding.small
-
- profile: PowerProfile.Performance
- icon: "rocket_launch"
- }
- }
-
- component Fill: AnchorChanges {
- required property Item item
-
- target: indicator
- anchors.left: item.left
- anchors.right: item.right
- anchors.top: item.top
- anchors.bottom: item.bottom
- }
-
- component Profile: Item {
- required property string icon
- required property int profile
-
- implicitWidth: icon.implicitHeight + Appearance.padding.small * 2
- implicitHeight: icon.implicitHeight + Appearance.padding.small * 2
-
- StateLayer {
- radius: Appearance.rounding.full
- color: profiles.current === parent.icon ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
-
- function onClicked(): void {
- PowerProfiles.profile = parent.profile;
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
-
- text: parent.icon
- font.pointSize: Appearance.font.size.large
- color: profiles.current === text ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
- fill: profiles.current === text ? 1 : 0
-
- Behavior on fill {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/Bluetooth.qml b/dots/quickshell/modules/bar/popouts/Bluetooth.qml
deleted file mode 100644
index ad7d087..0000000
--- a/dots/quickshell/modules/bar/popouts/Bluetooth.qml
+++ /dev/null
@@ -1,18 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Column {
- id: root
-
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Bluetooth %1").arg(Bluetooth.powered ? "enabled" : "disabled")
- }
-
- StyledText {
- text: Bluetooth.devices.some(d => d.connected) ? qsTr("Connected to: %1").arg(Bluetooth.devices.filter(d => d.connected).map(d => d.alias).join(", ")) : qsTr("No devices connected")
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/Content.qml b/dots/quickshell/modules/bar/popouts/Content.qml
deleted file mode 100644
index 43a0a09..0000000
--- a/dots/quickshell/modules/bar/popouts/Content.qml
+++ /dev/null
@@ -1,175 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Services.SystemTray
-import QtQuick
-
-Item {
- id: root
-
- required property ShellScreen screen
-
- property string currentName
- property real currentCenter
- property bool hasCurrent
-
- anchors.centerIn: parent
-
- implicitWidth: hasCurrent ? (content.children.find(c => c.shouldBeActive)?.implicitWidth ?? 0) + Appearance.padding.large * 2 : 0
- implicitHeight: (content.children.find(c => c.shouldBeActive)?.implicitHeight ?? 0) + Appearance.padding.large * 2
-
- Item {
- id: content
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large
-
- clip: true
-
- Popout {
- name: "activewindow"
- source: "ActiveWindow.qml"
- }
-
- Popout {
- name: "network"
- source: "Network.qml"
- }
-
- Popout {
- name: "bluetooth"
- source: "Bluetooth.qml"
- }
-
- Popout {
- name: "battery"
- source: "Battery.qml"
- }
-
- Repeater {
- model: ScriptModel {
- values: [...SystemTray.items.values]
- }
-
- Popout {
- id: trayMenu
-
- required property SystemTrayItem modelData
- required property int index
-
- name: `traymenu${index}`
- sourceComponent: trayMenuComp
-
- Connections {
- target: root
-
- function onHasCurrentChanged(): void {
- if (root.hasCurrent && trayMenu.shouldBeActive) {
- trayMenu.sourceComponent = null;
- trayMenu.sourceComponent = trayMenuComp;
- }
- }
- }
-
- Component {
- id: trayMenuComp
-
- TrayMenu {
- popouts: root
- trayItem: trayMenu.modelData.menu
- }
- }
- }
- }
- }
-
- Behavior on implicitWidth {
- Anim {
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on implicitHeight {
- enabled: root.implicitWidth > 0
-
- Anim {
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on currentCenter {
- enabled: root.implicitWidth > 0
-
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- component Popout: Loader {
- id: popout
-
- required property string name
- property bool shouldBeActive: root.currentName === name
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
-
- opacity: 0
- scale: 0.8
- active: false
- asynchronous: true
-
- states: State {
- name: "active"
- when: popout.shouldBeActive
-
- PropertyChanges {
- popout.active: true
- popout.opacity: 1
- popout.scale: 1
- }
- }
-
- transitions: [
- Transition {
- from: "active"
- to: ""
-
- SequentialAnimation {
- Anim {
- properties: "opacity,scale"
- duration: Appearance.anim.durations.small
- }
- PropertyAction {
- target: popout
- property: "active"
- }
- }
- },
- Transition {
- from: ""
- to: "active"
-
- SequentialAnimation {
- PropertyAction {
- target: popout
- property: "active"
- }
- Anim {
- properties: "opacity,scale"
- }
- }
- }
- ]
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/Network.qml b/dots/quickshell/modules/bar/popouts/Network.qml
deleted file mode 100644
index 7a79ef1..0000000
--- a/dots/quickshell/modules/bar/popouts/Network.qml
+++ /dev/null
@@ -1,22 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Column {
- id: root
-
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Connected to: %1").arg(Network.active?.ssid ?? "None")
- }
-
- StyledText {
- text: qsTr("Strength: %1/100").arg(Network.active?.strength ?? 0)
- }
-
- StyledText {
- text: qsTr("Frequency: %1 MHz").arg(Network.active?.frequency ?? 0)
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/TrayMenu.qml b/dots/quickshell/modules/bar/popouts/TrayMenu.qml
deleted file mode 100644
index 433de7f..0000000
--- a/dots/quickshell/modules/bar/popouts/TrayMenu.qml
+++ /dev/null
@@ -1,237 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Controls
-
-StackView {
- id: root
-
- required property Item popouts
- required property QsMenuHandle trayItem
-
- implicitWidth: currentItem.implicitWidth
- implicitHeight: currentItem.implicitHeight
-
- initialItem: SubMenu {
- handle: root.trayItem
- }
-
- pushEnter: Anim {}
- pushExit: Anim {}
- popEnter: Anim {}
- popExit: Anim {}
-
- component Anim: Transition {
- NumberAnimation {
- duration: 0
- }
- }
-
- component SubMenu: Column {
- id: menu
-
- required property QsMenuHandle handle
- property bool isSubMenu
- property bool shown
-
- padding: Appearance.padding.smaller
- spacing: Appearance.spacing.small
-
- opacity: shown ? 1 : 0
- scale: shown ? 1 : 0.8
-
- Component.onCompleted: shown = true
- StackView.onActivating: shown = true
- StackView.onDeactivating: shown = false
- StackView.onRemoved: destroy()
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on scale {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- QsMenuOpener {
- id: menuOpener
-
- menu: menu.handle
- }
-
- Repeater {
- model: menuOpener.children
-
- StyledRect {
- id: item
-
- required property QsMenuEntry modelData
-
- implicitWidth: Config.bar.sizes.trayMenuWidth
- implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight
-
- radius: Appearance.rounding.full
- color: modelData.isSeparator ? Colours.palette.m3outlineVariant : "transparent"
-
- Loader {
- id: children
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- active: !item.modelData.isSeparator
- asynchronous: true
-
- sourceComponent: Item {
- implicitHeight: label.implicitHeight
-
- StateLayer {
- anchors.margins: -Appearance.padding.small / 2
- anchors.leftMargin: -Appearance.padding.smaller
- anchors.rightMargin: -Appearance.padding.smaller
-
- radius: item.radius
- disabled: !item.modelData.enabled
-
- function onClicked(): void {
- const entry = item.modelData;
- if (entry.hasChildren)
- root.push(subMenuComp.createObject(null, {
- handle: entry,
- isSubMenu: true
- }));
- else {
- item.modelData.triggered();
- root.popouts.hasCurrent = false;
- }
- }
- }
-
- Loader {
- id: icon
-
- anchors.left: parent.left
-
- active: item.modelData.icon !== ""
- asynchronous: true
-
- sourceComponent: IconImage {
- implicitSize: label.implicitHeight
-
- source: item.modelData.icon
- }
- }
-
- StyledText {
- id: label
-
- anchors.left: icon.right
- anchors.leftMargin: icon.active ? Appearance.spacing.smaller : 0
-
- text: labelMetrics.elidedText
- color: item.modelData.enabled ? Colours.palette.m3onSurface : Colours.palette.m3outline
- }
-
- TextMetrics {
- id: labelMetrics
-
- text: item.modelData.text
- font.pointSize: label.font.pointSize
- font.family: label.font.family
-
- elide: Text.ElideRight
- elideWidth: Config.bar.sizes.trayMenuWidth - (icon.active ? icon.implicitWidth + label.anchors.leftMargin : 0) - (expand.active ? expand.implicitWidth + Appearance.spacing.normal : 0)
- }
-
- Loader {
- id: expand
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
-
- active: item.modelData.hasChildren
- asynchronous: true
-
- sourceComponent: MaterialIcon {
- text: "chevron_right"
- color: item.modelData.enabled ? Colours.palette.m3onSurface : Colours.palette.m3outline
- }
- }
- }
- }
- }
- }
-
- Loader {
- active: menu.isSubMenu
- asynchronous: true
-
- sourceComponent: Item {
- implicitWidth: back.implicitWidth
- implicitHeight: back.implicitHeight + Appearance.spacing.small / 2
-
- Item {
- anchors.bottom: parent.bottom
- implicitWidth: back.implicitWidth
- implicitHeight: back.implicitHeight
-
- StyledRect {
- anchors.fill: parent
- anchors.margins: -Appearance.padding.small / 2
- anchors.leftMargin: -Appearance.padding.smaller
- anchors.rightMargin: -Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: Colours.palette.m3secondaryContainer
-
- StateLayer {
- radius: parent.radius
- color: Colours.palette.m3onSecondaryContainer
-
- function onClicked(): void {
- root.pop();
- }
- }
- }
-
- Row {
- id: back
-
- anchors.verticalCenter: parent.verticalCenter
-
- MaterialIcon {
- anchors.verticalCenter: parent.verticalCenter
- text: "chevron_left"
- color: Colours.palette.m3onSecondaryContainer
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: qsTr("Back")
- color: Colours.palette.m3onSecondaryContainer
- }
- }
- }
- }
- }
- }
-
- Component {
- id: subMenuComp
-
- SubMenu {}
- }
-}
diff --git a/dots/quickshell/modules/bar/popouts/Wrapper.qml b/dots/quickshell/modules/bar/popouts/Wrapper.qml
deleted file mode 100644
index f304ea7..0000000
--- a/dots/quickshell/modules/bar/popouts/Wrapper.qml
+++ /dev/null
@@ -1,25 +0,0 @@
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property ShellScreen screen
-
- property alias currentName: content.currentName
- property alias currentCenter: content.currentCenter
- property alias hasCurrent: content.hasCurrent
-
- visible: width > 0 && height > 0
-
- implicitWidth: content.implicitWidth
- implicitHeight: content.implicitHeight
-
- Content {
- id: content
-
- screen: root.screen
- }
-}
diff --git a/dots/quickshell/modules/dashboard/Background.qml b/dots/quickshell/modules/dashboard/Background.qml
deleted file mode 100644
index 876311e..0000000
--- a/dots/quickshell/modules/dashboard/Background.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-import QtQuick
-import QtQuick.Shapes
-import "root:/config"
-import "root:/services"
-
-ShapePath {
- id: root
-
- required property Wrapper wrapper
- readonly property real rounding: Config.border.rounding
- readonly property bool flatten: wrapper.height < rounding * 2
- readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
-
- strokeWidth: -1
- fillColor: Config.border.colour
-
- PathArc {
- relativeX: root.rounding
- relativeY: root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- }
-
- PathLine {
- relativeX: 0
- relativeY: root.wrapper.height - root.roundingY * 2
- }
-
- PathArc {
- relativeX: root.rounding
- relativeY: root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- direction: PathArc.Counterclockwise
- }
-
- PathLine {
- relativeX: root.wrapper.width - root.rounding * 2
- relativeY: 0
- }
-
- PathArc {
- relativeX: root.rounding
- relativeY: -root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- direction: PathArc.Counterclockwise
- }
-
- PathLine {
- relativeX: 0
- relativeY: -(root.wrapper.height - root.roundingY * 2)
- }
-
- PathArc {
- relativeX: root.rounding
- relativeY: -root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- }
-
- Behavior on fillColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/Content.qml b/dots/quickshell/modules/dashboard/Content.qml
deleted file mode 100644
index 84079ef..0000000
--- a/dots/quickshell/modules/dashboard/Content.qml
+++ /dev/null
@@ -1,123 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-
-Item {
- id: root
-
- required property PersistentProperties visibilities
- readonly property real nonAnimWidth: view.implicitWidth + viewWrapper.anchors.margins * 2
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
-
- implicitWidth: nonAnimWidth
- implicitHeight: tabs.implicitHeight + tabs.anchors.topMargin + view.implicitHeight + viewWrapper.anchors.margins * 2
-
- Tabs {
- id: tabs
-
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.topMargin: Appearance.padding.normal
- anchors.margins: Appearance.padding.large
-
- nonAnimWidth: root.nonAnimWidth
- currentIndex: view.currentIndex
- }
-
- ClippingRectangle {
- id: viewWrapper
-
- anchors.top: tabs.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.margins: Appearance.padding.large
-
- radius: Appearance.rounding.normal
- color: "transparent"
-
- Flickable {
- id: view
-
- readonly property int currentIndex: tabs.currentIndex
- readonly property Item currentItem: row.children[currentIndex]
-
- anchors.fill: parent
-
- flickableDirection: Flickable.HorizontalFlick
-
- implicitWidth: currentItem.implicitWidth
- implicitHeight: currentItem.implicitHeight
-
- contentX: currentItem.x
- contentWidth: row.implicitWidth
- contentHeight: row.implicitHeight
-
- onContentXChanged: {
- if (!moving)
- return;
-
- const x = contentX - currentItem.x;
- if (x > currentItem.implicitWidth / 2)
- tabs.bar.incrementCurrentIndex();
- else if (x < -currentItem.implicitWidth / 2)
- tabs.bar.decrementCurrentIndex();
- }
-
- onDragEnded: {
- const x = contentX - currentItem.x;
- if (x > currentItem.implicitWidth / 10)
- tabs.bar.incrementCurrentIndex();
- else if (x < -currentItem.implicitWidth / 10)
- tabs.bar.decrementCurrentIndex();
- else
- contentX = Qt.binding(() => currentItem.x);
- }
-
- Row {
- id: row
-
- Dash {
- shouldUpdate: visible && this === view.currentItem
- }
-
- Media {
- shouldUpdate: visible && this === view.currentItem
- visibilities: root.visibilities
- }
-
- Performance {}
- }
-
- Behavior on contentX {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
- }
-
- Behavior on implicitWidth {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/Dash.qml b/dots/quickshell/modules/dashboard/Dash.qml
deleted file mode 100644
index 22132af..0000000
--- a/dots/quickshell/modules/dashboard/Dash.qml
+++ /dev/null
@@ -1,86 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import "dash"
-import QtQuick.Layouts
-
-GridLayout {
- id: root
-
- required property bool shouldUpdate
-
- rowSpacing: Appearance.spacing.normal
- columnSpacing: Appearance.spacing.normal
-
- Rect {
- Layout.column: 2
- Layout.columnSpan: 3
- Layout.preferredWidth: user.implicitWidth
- Layout.preferredHeight: user.implicitHeight
-
- User {
- id: user
- }
- }
-
- Rect {
- Layout.row: 0
- Layout.columnSpan: 2
- Layout.preferredWidth: Config.dashboard.sizes.weatherWidth
- Layout.fillHeight: true
-
- Weather {}
- }
-
- Rect {
- Layout.row: 1
- Layout.preferredWidth: dateTime.implicitWidth
- Layout.fillHeight: true
-
- DateTime {
- id: dateTime
- }
- }
-
- Rect {
- Layout.row: 1
- Layout.column: 1
- Layout.columnSpan: 3
- Layout.fillWidth: true
- Layout.preferredHeight: calendar.implicitHeight
-
- Calendar {
- id: calendar
- }
- }
-
- Rect {
- Layout.row: 1
- Layout.column: 4
- Layout.preferredWidth: resources.implicitWidth
- Layout.fillHeight: true
-
- Resources {
- id: resources
- }
- }
-
- Rect {
- Layout.row: 0
- Layout.column: 5
- Layout.rowSpan: 2
- Layout.preferredWidth: media.implicitWidth
- Layout.fillHeight: true
-
- Media {
- id: media
-
- shouldUpdate: root.shouldUpdate
- }
- }
-
- component Rect: StyledRect {
- radius: Appearance.rounding.small
- color: Colours.palette.m3surfaceContainer
- }
-}
diff --git a/dots/quickshell/modules/dashboard/Media.qml b/dots/quickshell/modules/dashboard/Media.qml
deleted file mode 100644
index 2d004d5..0000000
--- a/dots/quickshell/modules/dashboard/Media.qml
+++ /dev/null
@@ -1,594 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/utils"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import Quickshell.Services.Mpris
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Effects
-
-Item {
- id: root
-
- required property bool shouldUpdate
- required property PersistentProperties visibilities
-
- property real playerProgress: {
- const active = Players.active;
- return active?.length ? active.position / active.length : 0;
- }
-
- function lengthStr(length: int): string {
- if (length < 0)
- return "-1:-1";
- return `${Math.floor(length / 60)}:${Math.floor(length % 60).toString().padStart(2, "0")}`;
- }
-
- implicitWidth: cover.implicitWidth + Config.dashboard.sizes.mediaVisualiserSize * 2 + details.implicitWidth + details.anchors.leftMargin + bongocat.implicitWidth + bongocat.anchors.leftMargin * 2 + Appearance.padding.large * 2
- implicitHeight: Math.max(cover.implicitHeight + Config.dashboard.sizes.mediaVisualiserSize * 2, details.implicitHeight, bongocat.implicitHeight) + Appearance.padding.large * 2
-
- Behavior on playerProgress {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Timer {
- running: root.shouldUpdate && (Players.active?.isPlaying ?? false)
- interval: Config.dashboard.mediaUpdateInterval
- triggeredOnStart: true
- repeat: true
- onTriggered: Players.active?.positionChanged()
- }
-
- Connections {
- target: Cava
-
- function onValuesChanged(): void {
- if (root.shouldUpdate)
- visualiser.requestPaint();
- }
- }
-
- Canvas {
- id: visualiser
-
- readonly property real centerX: width / 2
- readonly property real centerY: height / 2
- readonly property real innerX: cover.implicitWidth / 2 + Appearance.spacing.small
- readonly property real innerY: cover.implicitHeight / 2 + Appearance.spacing.small
- property color colour: Colours.palette.m3primary
-
- anchors.fill: cover
- anchors.margins: -Config.dashboard.sizes.mediaVisualiserSize
-
- onColourChanged: requestPaint()
-
- onPaint: {
- const ctx = getContext("2d");
- ctx.reset();
-
- const values = Cava.values;
- const len = values.length;
-
- ctx.strokeStyle = colour;
- ctx.lineWidth = 360 / len - Appearance.spacing.small / 4;
- ctx.lineCap = "round";
-
- const size = Config.dashboard.sizes.mediaVisualiserSize;
- const cx = centerX;
- const cy = centerY;
- const rx = innerX + ctx.lineWidth / 2;
- const ry = innerY + ctx.lineWidth / 2;
-
- for (let i = 0; i < len; i++) {
- const v = Math.max(1, Math.min(100, values[i]));
-
- const angle = i * 2 * Math.PI / len;
- const magnitude = v / 100 * size;
- const cos = Math.cos(angle);
- const sin = Math.sin(angle);
-
- ctx.moveTo(cx + rx * cos, cy + ry * sin);
- ctx.lineTo(cx + (rx + magnitude) * cos, cy + (ry + magnitude) * sin);
- }
-
- ctx.stroke();
- }
-
- Behavior on colour {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- StyledClippingRect {
- id: cover
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: Appearance.padding.large + Config.dashboard.sizes.mediaVisualiserSize
-
- implicitWidth: Config.dashboard.sizes.mediaCoverArtSize
- implicitHeight: Config.dashboard.sizes.mediaCoverArtSize
-
- color: Colours.palette.m3surfaceContainerHigh
- radius: Appearance.rounding.full
-
- MaterialIcon {
- anchors.centerIn: parent
-
- text: "art_track"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: (parent.width * 0.4) || 1
- }
-
- Image {
- id: image
-
- anchors.fill: parent
-
- source: Players.active?.trackArtUrl ?? ""
- asynchronous: true
- fillMode: Image.PreserveAspectCrop
- sourceSize.width: width
- sourceSize.height: height
- }
- }
-
- Column {
- id: details
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: visualiser.right
- anchors.leftMargin: Appearance.spacing.normal
-
- spacing: Appearance.spacing.small
-
- StyledText {
- id: title
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- animate: true
- horizontalAlignment: Text.AlignHCenter
- text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.normal
-
- width: parent.implicitWidth
- elide: Text.ElideRight
- }
-
- StyledText {
- id: album
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- animate: true
- horizontalAlignment: Text.AlignHCenter
- text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
-
- width: parent.implicitWidth
- elide: Text.ElideRight
- }
-
- StyledText {
- id: artist
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- animate: true
- horizontalAlignment: Text.AlignHCenter
- text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
- color: Colours.palette.m3secondary
-
- width: parent.implicitWidth
- elide: Text.ElideRight
- }
-
- Row {
- id: controls
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- spacing: Appearance.spacing.small
-
- Control {
- icon: "skip_previous"
- canUse: Players.active?.canGoPrevious ?? false
-
- function onClicked(): void {
- Players.active?.previous();
- }
- }
-
- Control {
- icon: Players.active?.isPlaying ? "pause" : "play_arrow"
- canUse: Players.active?.canTogglePlaying ?? false
- primary: true
-
- function onClicked(): void {
- Players.active?.togglePlaying();
- }
- }
-
- Control {
- icon: "skip_next"
- canUse: Players.active?.canGoNext ?? false
-
- function onClicked(): void {
- Players.active?.next();
- }
- }
- }
-
- Slider {
- id: slider
-
- implicitWidth: controls.implicitWidth * 1.5
- implicitHeight: Appearance.padding.normal * 3
-
- value: root.playerProgress
- onMoved: {
- const active = Players.active;
- if (active?.canSeek && active?.positionSupported)
- active.position = value * active.length;
- }
-
- background: Item {
- StyledRect {
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.topMargin: slider.implicitHeight / 3
- anchors.bottomMargin: slider.implicitHeight / 3
-
- implicitWidth: slider.handle.x - slider.implicitHeight / 6
-
- color: Colours.palette.m3primary
- radius: Appearance.rounding.full
- topRightRadius: slider.implicitHeight / 15
- bottomRightRadius: slider.implicitHeight / 15
- }
-
- StyledRect {
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.right: parent.right
- anchors.topMargin: slider.implicitHeight / 3
- anchors.bottomMargin: slider.implicitHeight / 3
-
- implicitWidth: parent.width - slider.handle.x - slider.handle.implicitWidth - slider.implicitHeight / 6
-
- color: Colours.palette.m3surfaceContainer
- radius: Appearance.rounding.full
- topLeftRadius: slider.implicitHeight / 15
- bottomLeftRadius: slider.implicitHeight / 15
- }
- }
-
- handle: StyledRect {
- id: rect
-
- x: slider.visualPosition * slider.availableWidth
-
- implicitWidth: slider.implicitHeight / 4.5
- implicitHeight: slider.implicitHeight
-
- color: Colours.palette.m3primary
- radius: Appearance.rounding.full
-
- MouseArea {
- anchors.fill: parent
- cursorShape: Qt.PointingHandCursor
- onPressed: event => event.accepted = false
- }
- }
- }
-
- Item {
- anchors.left: parent.left
- anchors.right: parent.right
-
- implicitHeight: Math.max(position.implicitHeight, length.implicitHeight)
-
- StyledText {
- id: position
-
- anchors.left: parent.left
-
- text: root.lengthStr(Players.active?.position ?? -1)
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- id: length
-
- anchors.right: parent.right
-
- text: root.lengthStr(Players.active?.length ?? -1)
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- }
- }
-
- Row {
- anchors.horizontalCenter: parent.horizontalCenter
-
- spacing: Appearance.spacing.small
-
- Control {
- icon: "flip_to_front"
- canUse: Players.active?.canRaise ?? false
- fontSize: Appearance.font.size.larger
- padding: Appearance.padding.small
- fill: false
- color: Colours.palette.m3surfaceContainer
-
- function onClicked(): void {
- Players.active?.raise();
- root.visibilities.dashboard = false;
- }
- }
-
- MouseArea {
- id: playerSelector
-
- property bool expanded
-
- anchors.verticalCenter: parent.verticalCenter
-
- implicitWidth: slider.implicitWidth / 2
- implicitHeight: currentPlayer.implicitHeight + Appearance.padding.small * 2
-
- cursorShape: Qt.PointingHandCursor
- onClicked: expanded = !expanded
-
- RectangularShadow {
- anchors.fill: playerSelectorBg
-
- opacity: playerSelector.expanded ? 1 : 0
- radius: playerSelectorBg.radius
- color: Colours.palette.m3shadow
- blur: 5
- spread: 0
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- StyledRect {
- id: playerSelectorBg
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
-
- implicitHeight: playersWrapper.implicitHeight + Appearance.padding.small * 2
-
- color: Colours.palette.m3secondaryContainer
- radius: Appearance.rounding.normal
-
- Item {
- id: playersWrapper
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.margins: Appearance.padding.small
-
- clip: true
- implicitHeight: playerSelector.expanded && Players.list.length > 1 ? players.implicitHeight : currentPlayer.implicitHeight
-
- Column {
- id: players
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
-
- spacing: Appearance.spacing.small
-
- Repeater {
- model: Players.list.filter(p => p !== Players.active)
-
- Row {
- id: player
-
- required property MprisPlayer modelData
-
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Appearance.spacing.small
-
- IconImage {
- id: playerIcon
-
- source: Icons.getAppIcon(player.modelData.identity, "image-missing")
- implicitSize: Math.round(identity.implicitHeight * 0.9)
- }
-
- StyledText {
- id: identity
-
- text: identityMetrics.elidedText
- color: Colours.palette.m3onSecondaryContainer
-
- TextMetrics {
- id: identityMetrics
-
- text: player.modelData.identity
- font.family: identity.font.family
- font.pointSize: identity.font.pointSize
- elide: Text.ElideRight
- elideWidth: playerSelector.implicitWidth - playerIcon.implicitWidth - player.spacing - Appearance.padding.smaller * 2
- }
-
- MouseArea {
-
- anchors.fill: parent
-
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- Players.manualActive = player.modelData;
- playerSelector.expanded = false;
- }
- }
- }
- }
- }
-
- Item {
- anchors.left: parent.left
- anchors.right: parent.right
- implicitHeight: 1
-
- StyledRect {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: -Appearance.padding.normal
- color: Colours.palette.m3secondary
- implicitHeight: 1
- }
- }
-
- Row {
- id: currentPlayer
-
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Appearance.spacing.small
-
- IconImage {
- id: currentIcon
-
- source: Icons.getAppIcon(Players.active?.identity ?? "", "multimedia-player")
- implicitSize: Math.round(currentIdentity.implicitHeight * 0.9)
- }
-
- StyledText {
- id: currentIdentity
-
- animate: true
- text: currentIdentityMetrics.elidedText
- color: Colours.palette.m3onSecondaryContainer
-
- TextMetrics {
- id: currentIdentityMetrics
-
- text: Players.active?.identity ?? "No players"
- font.family: currentIdentity.font.family
- font.pointSize: currentIdentity.font.pointSize
- elide: Text.ElideRight
- elideWidth: playerSelector.implicitWidth - currentIcon.implicitWidth - currentPlayer.spacing - Appearance.padding.smaller * 2
- }
- }
- }
- }
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
- }
- }
-
- Control {
- icon: "delete"
- canUse: Players.active?.canQuit ?? false
- fontSize: Appearance.font.size.larger
- padding: Appearance.padding.small
- fill: false
- color: Colours.palette.m3surfaceContainer
-
- function onClicked(): void {
- Players.active?.quit();
- }
- }
- }
- }
-
- Item {
- id: bongocat
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: details.right
- anchors.leftMargin: Appearance.spacing.normal
-
- implicitWidth: visualiser.width
- implicitHeight: visualiser.height
-
- AnimatedImage {
- anchors.centerIn: parent
-
- width: visualiser.width * 0.75
- height: visualiser.height * 0.75
-
- playing: root.shouldUpdate && (Players.active?.isPlaying ?? false)
- speed: BeatDetector.bpm / 300
- source: "root:/assets/bongocat.gif"
- asynchronous: true
- fillMode: AnimatedImage.PreserveAspectFit
- }
- }
- component Control: StyledRect {
- id: control
-
- required property string icon
- required property bool canUse
- property int fontSize: Appearance.font.size.extraLarge
- property int padding
- property bool fill: true
- property bool primary
- function onClicked(): void {
- }
-
- implicitWidth: Math.max(icon.implicitWidth, icon.implicitHeight) + padding * 2
- implicitHeight: implicitWidth
-
- radius: Appearance.rounding.full
- color: primary && canUse ? Colours.palette.m3primary : "transparent"
-
- StateLayer {
- disabled: !control.canUse
- radius: parent.radius
- color: control.primary ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
-
- function onClicked(): void {
- control.onClicked();
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- anchors.verticalCenterOffset: font.pointSize * 0.05
-
- animate: true
- fill: control.fill ? 1 : 0
- text: control.icon
- color: control.canUse ? control.primary ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface : Colours.palette.m3outline
- font.pointSize: control.fontSize
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/Performance.qml b/dots/quickshell/modules/dashboard/Performance.qml
deleted file mode 100644
index b7bf8d0..0000000
--- a/dots/quickshell/modules/dashboard/Performance.qml
+++ /dev/null
@@ -1,230 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Row {
- id: root
-
- spacing: Appearance.spacing.large * 3
- padding: Appearance.padding.large
- leftPadding: padding * 2
- rightPadding: padding * 3
-
- Resource {
- value1: Math.min(1, SystemUsage.gpuTemp / 90)
- value2: SystemUsage.gpuPerc
-
- label1: `${Math.ceil(SystemUsage.gpuTemp)}°C`
- label2: `${Math.round(SystemUsage.gpuPerc * 100)}%`
-
- sublabel1: qsTr("GPU temp")
- sublabel2: qsTr("Usage")
- }
-
- Resource {
- primary: true
-
- value1: Math.min(1, SystemUsage.cpuTemp / 90)
- value2: SystemUsage.cpuPerc
-
- label1: `${Math.ceil(SystemUsage.cpuTemp)}°C`
- label2: `${Math.round(SystemUsage.cpuPerc * 100)}%`
-
- sublabel1: qsTr("CPU temp")
- sublabel2: qsTr("Usage")
- }
-
- Resource {
- value1: SystemUsage.memPerc
- value2: SystemUsage.storagePerc
-
- label1: {
- const fmt = SystemUsage.formatKib(SystemUsage.memUsed);
- return `${+fmt.value.toFixed(1)}${fmt.unit}`;
- }
- label2: {
- const fmt = SystemUsage.formatKib(SystemUsage.storageUsed);
- return `${Math.floor(fmt.value)}${fmt.unit}`;
- }
-
- sublabel1: qsTr("Memory")
- sublabel2: qsTr("Storage")
- }
-
- component Resource: Item {
- id: res
-
- required property real value1
- required property real value2
- required property string sublabel1
- required property string sublabel2
- required property string label1
- required property string label2
-
- property bool primary
- readonly property real primaryMult: primary ? 1.2 : 1
-
- readonly property real thickness: Config.dashboard.sizes.resourceProgessThickness * primaryMult
-
- property color fg1: Colours.palette.m3primary
- property color fg2: Colours.palette.m3secondary
- property color bg1: Colours.palette.m3primaryContainer
- property color bg2: Colours.palette.m3secondaryContainer
-
- anchors.verticalCenter: parent.verticalCenter
-
- implicitWidth: Config.dashboard.sizes.resourceSize * primaryMult
- implicitHeight: Config.dashboard.sizes.resourceSize * primaryMult
-
- onValue1Changed: canvas.requestPaint()
- onValue2Changed: canvas.requestPaint()
- onFg1Changed: canvas.requestPaint()
- onFg2Changed: canvas.requestPaint()
- onBg1Changed: canvas.requestPaint()
- onBg2Changed: canvas.requestPaint()
-
- Column {
- anchors.centerIn: parent
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
-
- text: res.label1
- font.pointSize: Appearance.font.size.extraLarge * res.primaryMult
- }
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
-
- text: res.sublabel1
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.smaller * res.primaryMult
- }
- }
-
- Column {
- anchors.horizontalCenter: parent.right
- anchors.top: parent.verticalCenter
- anchors.horizontalCenterOffset: -res.thickness / 2
- anchors.topMargin: res.thickness / 2 + Appearance.spacing.small
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
-
- text: res.label2
- font.pointSize: Appearance.font.size.smaller * res.primaryMult
- }
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
-
- text: res.sublabel2
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small * res.primaryMult
- }
- }
-
- Canvas {
- id: canvas
-
- readonly property real centerX: width / 2
- readonly property real centerY: height / 2
-
- readonly property real arc1Start: degToRad(45)
- readonly property real arc1End: degToRad(220)
- readonly property real arc2Start: degToRad(230)
- readonly property real arc2End: degToRad(360)
-
- function degToRad(deg: int): real {
- return deg * Math.PI / 180;
- }
-
- anchors.fill: parent
-
- onPaint: {
- const ctx = getContext("2d");
- ctx.reset();
-
- ctx.lineWidth = res.thickness;
- ctx.lineCap = "round";
-
- const radius = (Math.min(width, height) - ctx.lineWidth) / 2;
- const cx = centerX;
- const cy = centerY;
- const a1s = arc1Start;
- const a1e = arc1End;
- const a2s = arc2Start;
- const a2e = arc2End;
-
- ctx.beginPath();
- ctx.arc(cx, cy, radius, a1s, a1e, false);
- ctx.strokeStyle = res.bg1;
- ctx.stroke();
-
- ctx.beginPath();
- ctx.arc(cx, cy, radius, a1s, (a1e - a1s) * res.value1 + a1s, false);
- ctx.strokeStyle = res.fg1;
- ctx.stroke();
-
- ctx.beginPath();
- ctx.arc(cx, cy, radius, a2s, a2e, false);
- ctx.strokeStyle = res.bg2;
- ctx.stroke();
-
- ctx.beginPath();
- ctx.arc(cx, cy, radius, a2s, (a2e - a2s) * res.value2 + a2s, false);
- ctx.strokeStyle = res.fg2;
- ctx.stroke();
- }
- }
-
- Behavior on value1 {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on value2 {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on fg1 {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on fg2 {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on bg1 {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on bg2 {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/Tabs.qml b/dots/quickshell/modules/dashboard/Tabs.qml
deleted file mode 100644
index e678e6a..0000000
--- a/dots/quickshell/modules/dashboard/Tabs.qml
+++ /dev/null
@@ -1,250 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Controls
-
-Item {
- id: root
-
- required property real nonAnimWidth
- property alias currentIndex: bar.currentIndex
- readonly property TabBar bar: bar
-
- implicitHeight: bar.implicitHeight + indicator.implicitHeight + indicator.anchors.topMargin + separator.implicitHeight
-
- TabBar {
- id: bar
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
-
- background: null
-
- Tab {
- iconName: "dashboard"
- text: qsTr("Dashboard")
- }
-
- Tab {
- iconName: "queue_music"
- text: qsTr("Media")
- }
-
- Tab {
- iconName: "speed"
- text: qsTr("Performance")
- }
-
- // Tab {
- // iconName: "workspaces"
- // text: qsTr("Workspaces")
- // }
- }
-
- Item {
- id: indicator
-
- anchors.top: bar.bottom
- anchors.topMargin: Config.dashboard.sizes.tabIndicatorSpacing
-
- implicitWidth: bar.currentItem.implicitWidth
- implicitHeight: Config.dashboard.sizes.tabIndicatorHeight
-
- x: {
- const tab = bar.currentItem;
- const width = (root.nonAnimWidth - Config.dashboard.sizes.tabIndicatorSpacing * (bar.count - 1) * 2) / bar.count;
- return width * tab.TabBar.index + (width - tab.implicitWidth) / 2;
- }
-
- clip: true
-
- StyledRect {
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- implicitHeight: parent.implicitHeight * 2
-
- color: Colours.palette.m3primary
- radius: Appearance.rounding.full
- }
-
- Behavior on x {
- Anim {}
- }
-
- Behavior on implicitWidth {
- Anim {}
- }
- }
-
- StyledRect {
- id: separator
-
- anchors.top: indicator.bottom
- anchors.left: parent.left
- anchors.right: parent.right
-
- implicitHeight: 1
- color: Colours.palette.m3outlineVariant
- }
-
- component Tab: TabButton {
- id: tab
-
- required property string iconName
- readonly property bool current: TabBar.tabBar.currentItem === this
-
- background: null
-
- contentItem: MouseArea {
- id: mouse
-
- implicitWidth: Math.max(icon.width, label.width)
- implicitHeight: icon.height + label.height
-
- cursorShape: Qt.PointingHandCursor
-
- onPressed: ({
- x,
- y
- }) => {
- tab.TabBar.tabBar.setCurrentIndex(tab.TabBar.index);
-
- const stateY = stateWrapper.y;
- rippleAnim.x = x;
- rippleAnim.y = y - stateY;
-
- const dist = (ox, oy) => ox * ox + oy * oy;
- const stateEndY = stateY + stateWrapper.height;
- rippleAnim.radius = Math.sqrt(Math.max(dist(0, stateY), dist(0, stateEndY), dist(width, stateY), dist(width, stateEndY)));
-
- rippleAnim.restart();
- }
- onWheel: event => {
- if (event.angleDelta.y < 0)
- tab.TabBar.tabBar.incrementCurrentIndex();
- else if (event.angleDelta.y > 0)
- tab.TabBar.tabBar.decrementCurrentIndex();
- }
-
- SequentialAnimation {
- id: rippleAnim
-
- property real x
- property real y
- property real radius
-
- PropertyAction {
- target: ripple
- property: "x"
- value: rippleAnim.x
- }
- PropertyAction {
- target: ripple
- property: "y"
- value: rippleAnim.y
- }
- PropertyAction {
- target: ripple
- property: "opacity"
- value: 0.1
- }
- ParallelAnimation {
- Anim {
- target: ripple
- properties: "implicitWidth,implicitHeight"
- from: 0
- to: rippleAnim.radius * 2
- duration: Appearance.anim.durations.large
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- target: ripple
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
- }
-
- ClippingRectangle {
- id: stateWrapper
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- implicitHeight: parent.height + Config.dashboard.sizes.tabIndicatorSpacing * 2
-
- color: "transparent"
- radius: Appearance.rounding.small
-
- StyledRect {
- id: stateLayer
-
- anchors.fill: parent
-
- color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
- opacity: mouse.pressed ? 0.1 : tab.hovered ? 0.08 : 0
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- StyledRect {
- id: ripple
-
- radius: Appearance.rounding.full
- color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
- opacity: 0
-
- transform: Translate {
- x: -ripple.width / 2
- y: -ripple.height / 2
- }
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: label.top
-
- text: tab.iconName
- color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
- fill: tab.current ? 1 : 0
- font.pointSize: Appearance.font.size.large
-
- Behavior on fill {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- StyledText {
- id: label
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
-
- text: tab.text
- color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
- }
- }
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
-}
diff --git a/dots/quickshell/modules/dashboard/Wrapper.qml b/dots/quickshell/modules/dashboard/Wrapper.qml
deleted file mode 100644
index e043904..0000000
--- a/dots/quickshell/modules/dashboard/Wrapper.qml
+++ /dev/null
@@ -1,55 +0,0 @@
-import QtQuick
-import Quickshell
-import "root:/config"
-
-Item {
- id: root
-
- required property PersistentProperties visibilities
-
- visible: height > 0
- implicitHeight: 0
- implicitWidth: content.implicitWidth
-
- states: State {
- name: "visible"
- when: root.visibilities.dashboard
-
- PropertyChanges {
- root.implicitHeight: content.implicitHeight
- }
- }
-
- transitions: [
- Transition {
- from: ""
- to: "visible"
-
- NumberAnimation {
- target: root
- property: "implicitHeight"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- },
- Transition {
- from: "visible"
- to: ""
-
- NumberAnimation {
- target: root
- property: "implicitHeight"
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- ]
-
- Content {
- id: content
-
- visibilities: root.visibilities
- }
-}
diff --git a/dots/quickshell/modules/dashboard/dash/Calendar.qml b/dots/quickshell/modules/dashboard/dash/Calendar.qml
deleted file mode 100644
index aacea8f..0000000
--- a/dots/quickshell/modules/dashboard/dash/Calendar.qml
+++ /dev/null
@@ -1,72 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Controls
-
-Column {
- id: root
-
- anchors.left: parent.left
- anchors.right: parent.right
- padding: Appearance.padding.large
- spacing: Appearance.spacing.small
-
- DayOfWeekRow {
- id: days
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: parent.padding
-
- delegate: StyledText {
- required property var model
-
- horizontalAlignment: Text.AlignHCenter
- text: model.shortName
- font.family: Appearance.font.family.sans
- font.weight: 500
- }
- }
-
- MonthGrid {
- id: grid
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: parent.padding
-
- spacing: 3
-
- delegate: Item {
- id: day
-
- required property var model
-
- implicitWidth: implicitHeight
- implicitHeight: text.implicitHeight + Appearance.padding.small * 2
-
- StyledRect {
- anchors.centerIn: parent
-
- implicitWidth: parent.implicitHeight
- implicitHeight: parent.implicitHeight
-
- radius: Appearance.rounding.full
- color: model.today ? Colours.palette.m3primary : "transparent"
-
- StyledText {
- id: text
-
- anchors.centerIn: parent
-
- horizontalAlignment: Text.AlignHCenter
- text: grid.locale.toString(day.model.date, "d")
- color: day.model.today ? Colours.palette.m3onPrimary : day.model.month === grid.month ? Colours.palette.m3onSurfaceVariant : Colours.palette.m3outline
- }
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/dash/DateTime.qml b/dots/quickshell/modules/dashboard/dash/DateTime.qml
deleted file mode 100644
index 25df7a5..0000000
--- a/dots/quickshell/modules/dashboard/dash/DateTime.qml
+++ /dev/null
@@ -1,71 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Item {
- id: root
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- implicitWidth: Config.dashboard.sizes.dateTimeWidth
-
- StyledText {
- id: hours
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.topMargin: (root.height - (hours.implicitHeight + sep.implicitHeight + sep.anchors.topMargin + mins.implicitHeight + mins.anchors.topMargin + date.implicitHeight + date.anchors.topMargin)) / 2
-
- horizontalAlignment: Text.AlignHCenter
- text: Time.format("HH")
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
-
- StyledText {
- id: sep
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: hours.bottom
- anchors.topMargin: -font.pointSize * 0.5
-
- horizontalAlignment: Text.AlignHCenter
- text: "•••"
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.extraLarge * 0.9
- }
-
- StyledText {
- id: mins
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: sep.bottom
- anchors.topMargin: -sep.font.pointSize * 0.45
-
- horizontalAlignment: Text.AlignHCenter
- text: Time.format("mm")
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
-
- StyledText {
- id: date
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: mins.bottom
- anchors.topMargin: Appearance.spacing.normal
-
- horizontalAlignment: Text.AlignHCenter
- text: Time.format("ddd, d")
- color: Colours.palette.m3tertiary
- font.pointSize: Appearance.font.size.normal
- font.weight: 500
- }
-}
diff --git a/dots/quickshell/modules/dashboard/dash/Media.qml b/dots/quickshell/modules/dashboard/dash/Media.qml
deleted file mode 100644
index f47079d..0000000
--- a/dots/quickshell/modules/dashboard/dash/Media.qml
+++ /dev/null
@@ -1,262 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Io
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Shapes
-
-Item {
- id: root
-
- required property bool shouldUpdate
-
- property real playerProgress: {
- const active = Players.active;
- return active?.length ? active.position / active.length : 0;
- }
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- implicitWidth: Config.dashboard.sizes.mediaWidth
-
- Behavior on playerProgress {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Timer {
- running: root.shouldUpdate && (Players.active?.isPlaying ?? false)
- interval: Config.dashboard.mediaUpdateInterval
- triggeredOnStart: true
- repeat: true
- onTriggered: Players.active?.positionChanged()
- }
-
- Shape {
- preferredRendererType: Shape.CurveRenderer
-
- ShapePath {
- fillColor: "transparent"
- strokeColor: Colours.palette.m3surfaceContainerHigh
- strokeWidth: Config.dashboard.sizes.mediaProgressThickness
- capStyle: ShapePath.RoundCap
-
- PathAngleArc {
- centerX: cover.x + cover.width / 2
- centerY: cover.y + cover.height / 2
- radiusX: (cover.width + Config.dashboard.sizes.mediaProgressThickness) / 2 + Appearance.spacing.small
- radiusY: (cover.height + Config.dashboard.sizes.mediaProgressThickness) / 2 + Appearance.spacing.small
- startAngle: -90 - Config.dashboard.sizes.mediaProgressSweep / 2
- sweepAngle: Config.dashboard.sizes.mediaProgressSweep
- }
-
- Behavior on strokeColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- ShapePath {
- fillColor: "transparent"
- strokeColor: Colours.palette.m3primary
- strokeWidth: Config.dashboard.sizes.mediaProgressThickness
- capStyle: ShapePath.RoundCap
-
- PathAngleArc {
- centerX: cover.x + cover.width / 2
- centerY: cover.y + cover.height / 2
- radiusX: (cover.width + Config.dashboard.sizes.mediaProgressThickness) / 2 + Appearance.spacing.small
- radiusY: (cover.height + Config.dashboard.sizes.mediaProgressThickness) / 2 + Appearance.spacing.small
- startAngle: -90 - Config.dashboard.sizes.mediaProgressSweep / 2
- sweepAngle: Config.dashboard.sizes.mediaProgressSweep * root.playerProgress
- }
-
- Behavior on strokeColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
- }
-
- StyledClippingRect {
- id: cover
-
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
-
- implicitHeight: width
- color: Colours.palette.m3surfaceContainerHigh
- radius: Appearance.rounding.full
-
- MaterialIcon {
- anchors.centerIn: parent
-
- text: "art_track"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: (parent.width * 0.4) || 1
- }
-
- Image {
- id: image
-
- anchors.fill: parent
-
- source: Players.active?.trackArtUrl ?? ""
- asynchronous: true
- fillMode: Image.PreserveAspectCrop
- sourceSize.width: width
- sourceSize.height: height
- }
- }
-
- StyledText {
- id: title
-
- anchors.top: cover.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: Appearance.spacing.normal
-
- animate: true
- horizontalAlignment: Text.AlignHCenter
- text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.normal
-
- width: parent.implicitWidth - Appearance.padding.large * 2
- elide: Text.ElideRight
- }
-
- StyledText {
- id: album
-
- anchors.top: title.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: Appearance.spacing.small
-
- animate: true
- horizontalAlignment: Text.AlignHCenter
- text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
-
- width: parent.implicitWidth - Appearance.padding.large * 2
- elide: Text.ElideRight
- }
-
- StyledText {
- id: artist
-
- anchors.top: album.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: Appearance.spacing.small
-
- animate: true
- horizontalAlignment: Text.AlignHCenter
- text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
- color: Colours.palette.m3secondary
-
- width: parent.implicitWidth - Appearance.padding.large * 2
- elide: Text.ElideRight
- }
-
- Row {
- id: controls
-
- anchors.top: artist.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: Appearance.spacing.smaller
-
- spacing: Appearance.spacing.small
-
- Control {
- icon: "skip_previous"
- canUse: Players.active?.canGoPrevious ?? false
-
- function onClicked(): void {
- Players.active?.previous();
- }
- }
-
- Control {
- icon: Players.active?.isPlaying ? "pause" : "play_arrow"
- canUse: Players.active?.canTogglePlaying ?? false
-
- function onClicked(): void {
- Players.active?.togglePlaying();
- }
- }
-
- Control {
- icon: "skip_next"
- canUse: Players.active?.canGoNext ?? false
-
- function onClicked(): void {
- Players.active?.next();
- }
- }
- }
-
- AnimatedImage {
- id: bongocat
-
- anchors.top: controls.bottom
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.topMargin: Appearance.spacing.small
- anchors.bottomMargin: Appearance.padding.large
- anchors.margins: Appearance.padding.large * 2
-
- playing: root.shouldUpdate && (Players.active?.isPlaying ?? false)
- speed: BeatDetector.bpm / 300
- source: "root:/assets/bongocat.gif"
- asynchronous: true
- fillMode: AnimatedImage.PreserveAspectFit
- }
-
- component Control: StyledRect {
- id: control
-
- required property string icon
- required property bool canUse
- function onClicked(): void {
- }
-
- implicitWidth: Math.max(icon.implicitHeight, icon.implicitHeight) + Appearance.padding.small
- implicitHeight: implicitWidth
-
- StateLayer {
- disabled: !control.canUse
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- control.onClicked();
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- anchors.verticalCenterOffset: font.pointSize * 0.05
-
- animate: true
- text: control.icon
- color: control.canUse ? Colours.palette.m3onSurface : Colours.palette.m3outline
- font.pointSize: Appearance.font.size.large
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/dash/Resources.qml b/dots/quickshell/modules/dashboard/dash/Resources.qml
deleted file mode 100644
index 9a1f07a..0000000
--- a/dots/quickshell/modules/dashboard/dash/Resources.qml
+++ /dev/null
@@ -1,85 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Controls
-
-Row {
- id: root
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
-
- padding: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- Resource {
- icon: "memory"
- value: SystemUsage.cpuPerc
- colour: Colours.palette.m3primary
- }
-
- Resource {
- icon: "memory_alt"
- value: SystemUsage.memPerc
- colour: Colours.palette.m3secondary
- }
-
- Resource {
- icon: "hard_disk"
- value: SystemUsage.storagePerc
- colour: Colours.palette.m3tertiary
- }
-
- component Resource: Item {
- id: res
-
- required property string icon
- required property real value
- required property color colour
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.margins: Appearance.padding.large
- implicitWidth: icon.implicitWidth
-
- StyledRect {
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- anchors.bottom: icon.top
- anchors.bottomMargin: Appearance.spacing.small
-
- implicitWidth: Config.dashboard.sizes.resourceProgessThickness
-
- color: Colours.palette.m3surfaceContainerHigh
- radius: Appearance.rounding.full
-
- StyledRect {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- implicitHeight: res.value * parent.height
-
- color: res.colour
- radius: Appearance.rounding.full
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.bottom: parent.bottom
-
- text: res.icon
- color: res.colour
- }
-
- Behavior on value {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/dash/User.qml b/dots/quickshell/modules/dashboard/dash/User.qml
deleted file mode 100644
index bf989c6..0000000
--- a/dots/quickshell/modules/dashboard/dash/User.qml
+++ /dev/null
@@ -1,117 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import "root:/utils"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Row {
- id: root
-
- padding: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledClippingRect {
- implicitWidth: info.implicitHeight
- implicitHeight: info.implicitHeight
-
- radius: Appearance.rounding.large
- color: Colours.palette.m3surfaceContainerHigh
-
- MaterialIcon {
- anchors.centerIn: parent
-
- text: "person"
- fill: 1
- font.pointSize: (info.implicitHeight / 2) || 1
- }
-
- CachingImage {
- anchors.fill: parent
- path: `${Paths.home}/.face`
- }
- }
-
- Column {
- id: info
-
- anchors.verticalCenter: parent.verticalCenter
- spacing: Appearance.spacing.normal
-
- InfoLine {
- icon: Icons.osIcon
- text: Icons.osName
- colour: Colours.palette.m3primary
- }
-
- InfoLine {
- icon: "select_window_2"
- text: Quickshell.env("XDG_CURRENT_DESKTOP") || Quickshell.env("XDG_SESSION_DESKTOP")
- colour: Colours.palette.m3secondary
- }
-
- InfoLine {
- icon: "timer"
- text: uptimeProc.uptime
- colour: Colours.palette.m3tertiary
-
- Timer {
- running: true
- repeat: true
- interval: 15000
- onTriggered: uptimeProc.running = true
- }
-
- Process {
- id: uptimeProc
-
- property string uptime
-
- running: true
- command: ["uptime", "-p"]
- stdout: StdioCollector {
- onStreamFinished: uptimeProc.uptime = text.trim()
- }
- }
- }
- }
-
- component InfoLine: Item {
- id: line
-
- required property string icon
- required property string text
- required property color colour
-
- implicitWidth: icon.implicitWidth + text.width + text.anchors.leftMargin
- implicitHeight: Math.max(icon.implicitHeight, text.implicitHeight)
-
- MaterialIcon {
- id: icon
-
- anchors.left: parent.left
- anchors.leftMargin: (Config.dashboard.sizes.infoIconSize - implicitWidth) / 2
-
- text: line.icon
- color: line.colour
- font.pointSize: Appearance.font.size.normal
- font.variableAxes: ({
- FILL: 1
- })
- }
-
- StyledText {
- id: text
-
- anchors.verticalCenter: icon.verticalCenter
- anchors.left: icon.right
- anchors.leftMargin: icon.anchors.leftMargin
- text: `: ${line.text}`
- font.pointSize: Appearance.font.size.normal
-
- width: Config.dashboard.sizes.infoWidth
- elide: Text.ElideRight
- }
- }
-}
diff --git a/dots/quickshell/modules/dashboard/dash/Weather.qml b/dots/quickshell/modules/dashboard/dash/Weather.qml
deleted file mode 100644
index 468d542..0000000
--- a/dots/quickshell/modules/dashboard/dash/Weather.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import "root:/utils"
-import QtQuick
-
-Item {
- id: root
-
- anchors.centerIn: parent
-
- implicitWidth: icon.implicitWidth + info.implicitWidth + info.anchors.leftMargin
-
- onVisibleChanged: {
- if (visible)
- Weather.reload();
- }
-
- MaterialIcon {
- id: icon
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
-
- animate: true
- text: Weather.icon || "cloud_alert"
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.extraLarge * 2
- font.variableAxes: ({
- opsz: Appearance.font.size.extraLarge * 1.2
- })
- }
-
- Column {
- id: info
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: icon.right
- anchors.leftMargin: Appearance.spacing.large
-
- spacing: Appearance.spacing.small
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
-
- animate: true
- text: `${Weather.temperature}°C`
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
-
- animate: true
- text: Weather.description || qsTr("No weather")
-
- elide: Text.ElideRight
- width: Math.min(implicitWidth, root.parent.width - icon.implicitWidth - info.anchors.leftMargin - Appearance.padding.large * 2)
- }
- }
-}
diff --git a/dots/quickshell/modules/drawers/Backgrounds.qml b/dots/quickshell/modules/drawers/Backgrounds.qml
deleted file mode 100644
index 46ca477..0000000
--- a/dots/quickshell/modules/drawers/Backgrounds.qml
+++ /dev/null
@@ -1,66 +0,0 @@
-import "root:/services"
-import "root:/config"
-import "root:/modules/osd" as Osd
-import "root:/modules/notifications" as Notifications
-import "root:/modules/session" as Session
-import "root:/modules/launcher" as Launcher
-import "root:/modules/dashboard" as Dashboard
-import "root:/modules/bar/popouts" as BarPopouts
-import QtQuick
-import QtQuick.Shapes
-
-Shape {
- id: root
-
- required property Panels panels
- required property Item bar
-
- anchors.fill: parent
- anchors.margins: Config.border.thickness
- anchors.leftMargin: bar.implicitWidth
- preferredRendererType: Shape.CurveRenderer
- opacity: Colours.transparency.enabled ? Colours.transparency.base : 1
-
- Osd.Background {
- wrapper: panels.osd
-
- startX: root.width - panels.session.width
- startY: (root.height - wrapper.height) / 2 - rounding
- }
-
- Notifications.Background {
- wrapper: panels.notifications
-
- startX: root.width
- startY: 0
- }
-
- Session.Background {
- wrapper: panels.session
-
- startX: root.width
- startY: (root.height - wrapper.height) / 2 - rounding
- }
-
- Launcher.Background {
- wrapper: panels.launcher
-
- startX: (root.width - wrapper.width) / 2 - rounding
- startY: root.height
- }
-
- Dashboard.Background {
- wrapper: panels.dashboard
-
- startX: (root.width - wrapper.width) / 2 - rounding
- startY: 0
- }
-
- BarPopouts.Background {
- wrapper: panels.popouts
- invertBottomRounding: wrapper.y + wrapper.height + 1 >= root.height
-
- startX: 0
- startY: wrapper.y - rounding
- }
-}
diff --git a/dots/quickshell/modules/drawers/Border.qml b/dots/quickshell/modules/drawers/Border.qml
deleted file mode 100644
index 62dc277..0000000
--- a/dots/quickshell/modules/drawers/Border.qml
+++ /dev/null
@@ -1,47 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-import QtQuick.Effects
-
-Item {
- id: root
-
- required property Item bar
-
- anchors.fill: parent
-
- StyledRect {
- id: rect
-
- anchors.fill: parent
- color: Colours.alpha(Config.border.colour, false)
- visible: false
- }
-
- Item {
- id: mask
-
- anchors.fill: parent
- layer.enabled: true
- visible: false
-
- Rectangle {
- anchors.fill: parent
- anchors.margins: Config.border.thickness
- anchors.leftMargin: root.bar.implicitWidth
- radius: Config.border.rounding
- }
- }
-
- MultiEffect {
- anchors.fill: parent
- maskEnabled: true
- maskInverted: true
- maskSource: mask
- source: rect
- maskThresholdMin: 0.5
- maskSpreadAtMin: 1
- }
-}
diff --git a/dots/quickshell/modules/drawers/Drawers.qml b/dots/quickshell/modules/drawers/Drawers.qml
deleted file mode 100644
index 5cab75b..0000000
--- a/dots/quickshell/modules/drawers/Drawers.qml
+++ /dev/null
@@ -1,147 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import "root:/modules/bar"
-import Quickshell
-import Quickshell.Wayland
-import Quickshell.Hyprland
-import QtQuick
-import QtQuick.Effects
-
-Variants {
- model: Quickshell.screens
-
- Scope {
- id: scope
-
- required property ShellScreen modelData
-
- Exclusions {
- screen: scope.modelData
- bar: bar
- }
-
- StyledWindow {
- id: win
-
- screen: scope.modelData
- name: "drawers"
- WlrLayershell.exclusionMode: ExclusionMode.Ignore
- WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.session ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
-
- mask: Region {
- x: bar.implicitWidth
- y: Config.border.thickness
- width: win.width - bar.implicitWidth - Config.border.thickness
- height: win.height - Config.border.thickness * 2
- intersection: Intersection.Xor
-
- regions: regions.instances
- }
-
- anchors.top: true
- anchors.bottom: true
- anchors.left: true
- anchors.right: true
-
- Variants {
- id: regions
-
- model: panels.children
-
- Region {
- required property Item modelData
-
- x: modelData.x + bar.implicitWidth
- y: modelData.y + Config.border.thickness
- width: modelData.width
- height: modelData.height
- intersection: Intersection.Subtract
- }
- }
-
- HyprlandFocusGrab {
- active: visibilities.launcher || visibilities.session
- windows: [win]
- onCleared: {
- visibilities.launcher = false;
- visibilities.session = false;
- }
- }
-
- StyledRect {
- anchors.fill: parent
- opacity: visibilities.session ? 0.5 : 0
- color: Colours.palette.m3scrim
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- Item {
- id: background
-
- anchors.fill: parent
- visible: false
-
- Border {
- bar: bar
- }
-
- Backgrounds {
- panels: panels
- bar: bar
- }
- }
-
- MultiEffect {
- anchors.fill: source
- source: background
- shadowEnabled: true
- blurMax: 15
- shadowColor: Qt.alpha(Colours.palette.m3shadow, 0.7)
- }
-
- PersistentProperties {
- id: visibilities
-
- property bool osd
- property bool session
- property bool launcher
- property bool dashboard
-
- Component.onCompleted: Visibilities.screens[scope.modelData] = this
- }
-
- Interactions {
- screen: scope.modelData
- popouts: panels.popouts
- visibilities: visibilities
- panels: panels
- bar: bar
-
- Panels {
- id: panels
-
- screen: scope.modelData
- visibilities: visibilities
- bar: bar
- }
- }
-
- Bar {
- id: bar
-
- screen: scope.modelData
- popouts: panels.popouts
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/drawers/Exclusions.qml b/dots/quickshell/modules/drawers/Exclusions.qml
deleted file mode 100644
index 5557cdb..0000000
--- a/dots/quickshell/modules/drawers/Exclusions.qml
+++ /dev/null
@@ -1,37 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Scope {
- id: root
-
- required property ShellScreen screen
- required property Item bar
-
- ExclusionZone {
- anchors.left: true
- exclusiveZone: root.bar.implicitWidth
- }
-
- ExclusionZone {
- anchors.top: true
- }
-
- ExclusionZone {
- anchors.right: true
- }
-
- ExclusionZone {
- anchors.bottom: true
- }
-
- component ExclusionZone: StyledWindow {
- screen: root.screen
- name: "border-exclusion"
- exclusiveZone: Config.border.thickness
- mask: Region {}
- }
-}
diff --git a/dots/quickshell/modules/drawers/Interactions.qml b/dots/quickshell/modules/drawers/Interactions.qml
deleted file mode 100644
index d38cc8a..0000000
--- a/dots/quickshell/modules/drawers/Interactions.qml
+++ /dev/null
@@ -1,160 +0,0 @@
-import "root:/services"
-import "root:/config"
-import "root:/modules/bar/popouts" as BarPopouts
-import "root:/modules/osd" as Osd
-import Quickshell
-import QtQuick
-
-MouseArea {
- id: root
-
- required property ShellScreen screen
- required property BarPopouts.Wrapper popouts
- required property PersistentProperties visibilities
- required property Panels panels
- required property Item bar
-
- property bool osdHovered
- property point dragStart
- property bool dashboardShortcutActive
- property bool osdShortcutActive
-
- function withinPanelHeight(panel: Item, x: real, y: real): bool {
- const panelY = Config.border.thickness + panel.y;
- return y >= panelY - Config.border.rounding && y <= panelY + panel.height + Config.border.rounding;
- }
-
- function inRightPanel(panel: Item, x: real, y: real): bool {
- return x > bar.implicitWidth + panel.x && withinPanelHeight(panel, x, y);
- }
-
- function inTopPanel(panel: Item, x: real, y: real): bool {
- const panelX = bar.implicitWidth + panel.x;
- return y < Config.border.thickness + panel.y + panel.height && x >= panelX - Config.border.rounding && x <= panelX + panel.width + Config.border.rounding;
- }
-
- anchors.fill: parent
- hoverEnabled: true
-
- onPressed: event => dragStart = Qt.point(event.x, event.y)
- onContainsMouseChanged: {
- if (!containsMouse) {
- // Only hide if not activated by shortcut
- if (!osdShortcutActive) {
- visibilities.osd = false;
- osdHovered = false;
- }
- if (!dashboardShortcutActive) {
- visibilities.dashboard = false;
- }
- popouts.hasCurrent = false;
- }
- }
-
- onPositionChanged: ({
- x,
- y
- }) => {
- // Show osd on hover
- const showOsd = inRightPanel(panels.osd, x, y);
-
- // Always update visibility based on hover if not in shortcut mode
- if (!osdShortcutActive) {
- visibilities.osd = showOsd;
- osdHovered = showOsd;
- } else if (showOsd) {
- // If hovering over OSD area while in shortcut mode, transition to hover control
- osdShortcutActive = false;
- osdHovered = true;
- }
-
- // Show/hide session on drag
- if (pressed && withinPanelHeight(panels.session, x, y)) {
- const dragX = x - dragStart.x;
- if (dragX < -Config.session.dragThreshold)
- visibilities.session = true;
- else if (dragX > Config.session.dragThreshold)
- visibilities.session = false;
- }
-
- // Show dashboard on hover
- const showDashboard = inTopPanel(panels.dashboard, x, y);
-
- // Always update visibility based on hover if not in shortcut mode
- if (!dashboardShortcutActive) {
- visibilities.dashboard = showDashboard;
- } else if (showDashboard) {
- // If hovering over dashboard area while in shortcut mode, transition to hover control
- dashboardShortcutActive = false;
- }
-
- // Show popouts on hover
- const popout = panels.popouts;
- if (x < bar.implicitWidth + popout.width) {
- if (x < bar.implicitWidth)
- // Handle like part of bar
- bar.checkPopout(y);
- else
- // Keep on hover
- popouts.hasCurrent = withinPanelHeight(popout, x, y);
- } else
- popouts.hasCurrent = false;
- }
-
- // Monitor individual visibility changes
- Connections {
- target: root.visibilities
-
- function onLauncherChanged() {
- // If launcher is hidden, clear shortcut flags for dashboard and OSD
- if (!root.visibilities.launcher) {
- root.dashboardShortcutActive = false;
- root.osdShortcutActive = false;
-
- // Also hide dashboard and OSD if they're not being hovered
- const inDashboardArea = root.inTopPanel(root.panels.dashboard, root.mouseX, root.mouseY);
- const inOsdArea = root.inRightPanel(root.panels.osd, root.mouseX, root.mouseY);
-
- if (!inDashboardArea) {
- root.visibilities.dashboard = false;
- }
- if (!inOsdArea) {
- root.visibilities.osd = false;
- root.osdHovered = false;
- }
- }
- }
-
- function onDashboardChanged() {
- if (root.visibilities.dashboard) {
- // Dashboard became visible, immediately check if this should be shortcut mode
- const inDashboardArea = root.inTopPanel(root.panels.dashboard, root.mouseX, root.mouseY);
- if (!inDashboardArea) {
- root.dashboardShortcutActive = true;
- }
- } else {
- // Dashboard hidden, clear shortcut flag
- root.dashboardShortcutActive = false;
- }
- }
-
- function onOsdChanged() {
- if (root.visibilities.osd) {
- // OSD became visible, immediately check if this should be shortcut mode
- const inOsdArea = root.inRightPanel(root.panels.osd, root.mouseX, root.mouseY);
- if (!inOsdArea) {
- root.osdShortcutActive = true;
- }
- } else {
- // OSD hidden, clear shortcut flag
- root.osdShortcutActive = false;
- }
- }
- }
-
- Osd.Interactions {
- screen: root.screen
- visibilities: root.visibilities
- hovered: root.osdHovered
- }
-}
diff --git a/dots/quickshell/modules/drawers/Panels.qml b/dots/quickshell/modules/drawers/Panels.qml
deleted file mode 100644
index a422fcc..0000000
--- a/dots/quickshell/modules/drawers/Panels.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-import "root:/services"
-import "root:/config"
-import "root:/modules/osd" as Osd
-import "root:/modules/notifications" as Notifications
-import "root:/modules/session" as Session
-import "root:/modules/launcher" as Launcher
-import "root:/modules/dashboard" as Dashboard
-import "root:/modules/bar/popouts" as BarPopouts
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property PersistentProperties visibilities
- required property Item bar
-
- readonly property Osd.Wrapper osd: osd
- readonly property Notifications.Wrapper notifications: notifications
- readonly property Session.Wrapper session: session
- readonly property Launcher.Wrapper launcher: launcher
- readonly property Dashboard.Wrapper dashboard: dashboard
- readonly property BarPopouts.Wrapper popouts: popouts
-
- anchors.fill: parent
- anchors.margins: Config.border.thickness
- anchors.leftMargin: bar.implicitWidth
-
- Component.onCompleted: Visibilities.panels[screen] = this
-
- Osd.Wrapper {
- id: osd
-
- clip: root.visibilities.session
- screen: root.screen
- visibility: root.visibilities.osd
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- anchors.rightMargin: session.width
- }
-
- Notifications.Wrapper {
- id: notifications
-
- anchors.top: parent.top
- anchors.right: parent.right
- }
-
- Session.Wrapper {
- id: session
-
- visibilities: root.visibilities
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- }
-
- Launcher.Wrapper {
- id: launcher
-
- visibilities: root.visibilities
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- }
-
- Dashboard.Wrapper {
- id: dashboard
-
- visibilities: root.visibilities
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- }
-
- BarPopouts.Wrapper {
- id: popouts
-
- screen: root.screen
-
- anchors.left: parent.left
- anchors.verticalCenter: parent.top
- anchors.verticalCenterOffset: {
- const off = root.popouts.currentCenter - Config.border.thickness;
- const diff = root.height - Math.floor(off + implicitHeight / 2);
- if (diff < 0)
- return off + diff;
- return off;
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/ActionItem.qml b/dots/quickshell/modules/launcher/ActionItem.qml
deleted file mode 100644
index db3242a..0000000
--- a/dots/quickshell/modules/launcher/ActionItem.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Item {
- id: root
-
- required property Actions.Action modelData
- required property var list
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- root.modelData?.onClicked(root.list);
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- MaterialIcon {
- id: icon
-
- text: root.modelData?.icon ?? ""
- font.pointSize: Appearance.font.size.extraLarge
-
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Item {
- anchors.left: icon.right
- anchors.leftMargin: Appearance.spacing.larger
- anchors.verticalCenter: icon.verticalCenter
-
- implicitWidth: parent.width - icon.width
- implicitHeight: name.implicitHeight + desc.implicitHeight
-
- StyledText {
- id: name
-
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- id: desc
-
- text: root.modelData?.desc ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.alpha(Colours.palette.m3outline, true)
-
- elide: Text.ElideRight
- width: root.width - icon.width - Appearance.rounding.normal * 2
-
- anchors.top: name.bottom
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/Actions.qml b/dots/quickshell/modules/launcher/Actions.qml
deleted file mode 100644
index 9f6f52c..0000000
--- a/dots/quickshell/modules/launcher/Actions.qml
+++ /dev/null
@@ -1,152 +0,0 @@
-pragma Singleton
-
-import "root:/utils/scripts/fuzzysort.js" as Fuzzy
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property list list: [
- Action {
- name: qsTr("Scheme")
- desc: qsTr("Change the current colour scheme")
- icon: "palette"
-
- function onClicked(list: AppList): void {
- root.autocomplete(list, "scheme");
- }
- },
- Action {
- name: qsTr("Wallpaper")
- desc: qsTr("Change the current wallpaper")
- icon: "image"
-
- function onClicked(list: AppList): void {
- root.autocomplete(list, "wallpaper");
- }
- },
- Action {
- name: qsTr("Variant")
- desc: qsTr("Change the current scheme variant")
- icon: "colors"
-
- function onClicked(list: AppList): void {
- root.autocomplete(list, "variant");
- }
- },
- Action {
- name: qsTr("Transparency")
- desc: qsTr("Change shell transparency")
- icon: "opacity"
-
- function onClicked(list: AppList): void {
- root.autocomplete(list, "transparency");
- }
- },
- Action {
- name: qsTr("Light")
- desc: qsTr("Change the scheme to light mode")
- icon: "light_mode"
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Colours.setMode("light");
- }
- },
- Action {
- name: qsTr("Dark")
- desc: qsTr("Change the scheme to dark mode")
- icon: "dark_mode"
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Colours.setMode("dark");
- }
- },
- Action {
- name: qsTr("Shutdown")
- desc: qsTr("Shutdown the system")
- icon: "power_settings_new"
- disabled: !Config.launcher.enableDangerousActions
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Quickshell.execDetached(["systemctl", "poweroff"]);
- }
- },
- Action {
- name: qsTr("Reboot")
- desc: qsTr("Reboot the system")
- icon: "cached"
- disabled: !Config.launcher.enableDangerousActions
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Quickshell.execDetached(["systemctl", "reboot"]);
- }
- },
- Action {
- name: qsTr("Logout")
- desc: qsTr("Log out of the current session")
- icon: "exit_to_app"
- disabled: !Config.launcher.enableDangerousActions
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Quickshell.execDetached(["sh", "-c", "(uwsm stop | grep -q 'Compositor is not running' && loginctl terminate-user $USER) || uwsm stop"]);
- }
- },
- Action {
- name: qsTr("Lock")
- desc: qsTr("Lock the current session")
- icon: "lock"
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Quickshell.execDetached(["loginctl", "lock-session"]);
- }
- },
- Action {
- name: qsTr("Sleep")
- desc: qsTr("Suspend then hibernate")
- icon: "bedtime"
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Quickshell.execDetached(["systemctl", "suspend-then-hibernate"]);
- }
- }
- ]
-
- readonly property list preppedActions: list.filter(a => !a.disabled).map(a => ({
- name: Fuzzy.prepare(a.name),
- desc: Fuzzy.prepare(a.desc),
- action: a
- }))
-
- function fuzzyQuery(search: string): var {
- return Fuzzy.go(search.slice(Config.launcher.actionPrefix.length), preppedActions, {
- all: true,
- keys: ["name", "desc"],
- scoreFn: r => r[0].score > 0 ? r[0].score * 0.9 + r[1].score * 0.1 : 0
- }).map(r => r.obj.action);
- }
-
- function autocomplete(list: AppList, text: string): void {
- list.search.text = `${Config.launcher.actionPrefix}${text} `;
- }
-
- component Action: QtObject {
- required property string name
- required property string desc
- required property string icon
- property bool disabled
-
- function onClicked(list: AppList): void {
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/AppItem.qml b/dots/quickshell/modules/launcher/AppItem.qml
deleted file mode 100644
index e3f6720..0000000
--- a/dots/quickshell/modules/launcher/AppItem.qml
+++ /dev/null
@@ -1,72 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-
-Item {
- id: root
-
- required property DesktopEntry modelData
- required property PersistentProperties visibilities
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- Apps.launch(root.modelData);
- root.visibilities.launcher = false;
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- IconImage {
- id: icon
-
- source: Quickshell.iconPath(root.modelData?.icon, "image-missing")
- implicitSize: parent.height * 0.8
-
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Item {
- anchors.left: icon.right
- anchors.leftMargin: Appearance.spacing.normal
- anchors.verticalCenter: icon.verticalCenter
-
- implicitWidth: parent.width - icon.width
- implicitHeight: name.implicitHeight + comment.implicitHeight
-
- StyledText {
- id: name
-
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- id: comment
-
- text: (root.modelData?.comment || root.modelData?.genericName || root.modelData?.name) ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.alpha(Colours.palette.m3outline, true)
-
- elide: Text.ElideRight
- width: root.width - icon.width - Appearance.rounding.normal * 2
-
- anchors.top: name.bottom
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/AppList.qml b/dots/quickshell/modules/launcher/AppList.qml
deleted file mode 100644
index c06893a..0000000
--- a/dots/quickshell/modules/launcher/AppList.qml
+++ /dev/null
@@ -1,199 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-import QtQuick.Controls
-
-ListView {
- id: root
-
- required property TextField search
- required property PersistentProperties visibilities
-
- property bool isAction: search.text.startsWith(Config.launcher.actionPrefix)
- property bool isScheme: search.text.startsWith(`${Config.launcher.actionPrefix}scheme `)
- property bool isVariant: search.text.startsWith(`${Config.launcher.actionPrefix}variant `)
-
- function getModelValues() {
- let text = search.text;
- if (isScheme)
- return Schemes.fuzzyQuery(text);
- if (isVariant)
- return M3Variants.fuzzyQuery(text);
- if (isAction)
- return Actions.fuzzyQuery(text);
- if (text.startsWith(Config.launcher.actionPrefix))
- text = search.text.slice(Config.launcher.actionPrefix.length);
- return Apps.fuzzyQuery(text);
- }
-
- model: ScriptModel {
- values: root.getModelValues()
- onValuesChanged: root.currentIndex = 0
- }
-
- spacing: Appearance.spacing.small
- orientation: Qt.Vertical
- implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxShown, count) - spacing
-
- highlightMoveDuration: Appearance.anim.durations.normal
- highlightResizeDuration: 0
-
- highlight: StyledRect {
- radius: Appearance.rounding.full
- color: Colours.palette.m3onSurface
- opacity: 0.08
- }
-
- delegate: {
- if (isScheme)
- return schemeItem;
- if (isVariant)
- return variantItem;
- if (isAction)
- return actionItem;
- return appItem;
- }
-
- ScrollBar.vertical: StyledScrollBar {}
-
- add: Transition {
- Anim {
- properties: "opacity,scale"
- from: 0
- to: 1
- }
- }
-
- remove: Transition {
- Anim {
- properties: "opacity,scale"
- from: 1
- to: 0
- }
- }
-
- move: Transition {
- Anim {
- property: "y"
- }
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- }
-
- addDisplaced: Transition {
- Anim {
- property: "y"
- duration: Appearance.anim.durations.small
- }
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- }
-
- displaced: Transition {
- Anim {
- property: "y"
- }
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- }
-
- Component {
- id: appItem
-
- AppItem {
- visibilities: root.visibilities
- }
- }
-
- Component {
- id: actionItem
-
- ActionItem {
- list: root
- }
- }
-
- Component {
- id: schemeItem
-
- SchemeItem {
- list: root
- }
- }
-
- Component {
- id: variantItem
-
- VariantItem {
- list: root
- }
- }
-
- Behavior on isAction {
- ChangeAnim {}
- }
-
- Behavior on isScheme {
- ChangeAnim {}
- }
-
- Behavior on isVariant {
- ChangeAnim {}
- }
-
- component ChangeAnim: SequentialAnimation {
- ParallelAnimation {
- Anim {
- target: root
- property: "opacity"
- from: 1
- to: 0
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.standardAccel
- }
- Anim {
- target: root
- property: "scale"
- from: 1
- to: 0.9
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.standardAccel
- }
- }
- PropertyAction {}
- ParallelAnimation {
- Anim {
- target: root
- property: "opacity"
- from: 0
- to: 1
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- target: root
- property: "scale"
- from: 0.9
- to: 1
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
-}
diff --git a/dots/quickshell/modules/launcher/Background.qml b/dots/quickshell/modules/launcher/Background.qml
deleted file mode 100644
index 82c5f4a..0000000
--- a/dots/quickshell/modules/launcher/Background.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Shapes
-
-ShapePath {
- id: root
-
- required property Wrapper wrapper
- readonly property real rounding: Config.border.rounding
- readonly property bool flatten: wrapper.height < rounding * 2
- readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
-
- strokeWidth: -1
- fillColor: Config.border.colour
-
- PathArc {
- relativeX: root.rounding
- relativeY: -root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: -(root.wrapper.height - root.roundingY * 2)
- }
- PathArc {
- relativeX: root.rounding
- relativeY: -root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- }
- PathLine {
- relativeX: root.wrapper.width - root.rounding * 2
- relativeY: 0
- }
- PathArc {
- relativeX: root.rounding
- relativeY: root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- }
- PathLine {
- relativeX: 0
- relativeY: root.wrapper.height - root.roundingY * 2
- }
- PathArc {
- relativeX: root.rounding
- relativeY: root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- direction: PathArc.Counterclockwise
- }
-
- Behavior on fillColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/Content.qml b/dots/quickshell/modules/launcher/Content.qml
deleted file mode 100644
index b6d1056..0000000
--- a/dots/quickshell/modules/launcher/Content.qml
+++ /dev/null
@@ -1,168 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property PersistentProperties visibilities
- readonly property int padding: Appearance.padding.large
- readonly property int rounding: Appearance.rounding.large
-
- implicitWidth: listWrapper.width + padding * 2
- implicitHeight: searchWrapper.height + listWrapper.height + padding * 2
-
- anchors.top: parent.top
- anchors.horizontalCenter: parent.horizontalCenter
-
- Item {
- id: listWrapper
-
- implicitWidth: list.width
- implicitHeight: list.height + root.padding
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: searchWrapper.top
- anchors.bottomMargin: root.padding
-
- ContentList {
- id: list
-
- visibilities: root.visibilities
- search: search
- padding: root.padding
- rounding: root.rounding
- }
- }
-
- StyledRect {
- id: searchWrapper
-
- color: Colours.alpha(Colours.palette.m3surfaceContainer, true)
- radius: Appearance.rounding.full
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.margins: root.padding
-
- implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight)
-
- MaterialIcon {
- id: searchIcon
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: root.padding
-
- text: "search"
- color: Colours.palette.m3onSurfaceVariant
- }
-
- StyledTextField {
- id: search
-
- anchors.left: searchIcon.right
- anchors.right: clearIcon.left
- anchors.leftMargin: Appearance.spacing.small
- anchors.rightMargin: Appearance.spacing.small
-
- topPadding: Appearance.padding.larger
- bottomPadding: Appearance.padding.larger
-
- placeholderText: qsTr("Type \"%1\" for commands").arg(Config.launcher.actionPrefix)
- background: null
-
- onAccepted: {
- const currentItem = list.currentList?.currentItem;
- if (currentItem) {
- if (list.showWallpapers) {
- Wallpapers.setWallpaper(currentItem.modelData.path);
- root.visibilities.launcher = false;
- } else if (text.startsWith(Config.launcher.actionPrefix)) {
- currentItem.modelData.onClicked(list.currentList);
- } else {
- Apps.launch(currentItem.modelData);
- root.visibilities.launcher = false;
- }
- }
- }
-
- Keys.onUpPressed: list.currentList?.decrementCurrentIndex()
- Keys.onDownPressed: list.currentList?.incrementCurrentIndex()
-
- Keys.onEscapePressed: root.visibilities.launcher = false
-
- Connections {
- target: root.visibilities
-
- function onLauncherChanged(): void {
- if (root.visibilities.launcher)
- search.forceActiveFocus();
- else {
- search.text = "";
- const current = list.currentList;
- if (current)
- current.currentIndex = 0;
- }
- }
- }
- }
-
- MaterialIcon {
- id: clearIcon
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- anchors.rightMargin: root.padding
-
- width: search.text ? implicitWidth : implicitWidth / 2
- opacity: {
- if (!search.text)
- return 0;
- if (mouse.pressed)
- return 0.7;
- if (mouse.hovered)
- return 0.8;
- return 1;
- }
-
- text: "close"
- color: Colours.palette.m3onSurfaceVariant
-
- MouseArea {
- id: mouse
-
- property bool hovered
-
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: search.text ? Qt.PointingHandCursor : undefined
-
- onEntered: hovered = true
- onExited: hovered = false
- onClicked: search.text = ""
- }
-
- Behavior on width {
- NumberAnimation {
- duration: Appearance.anim.durations.small
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.small
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/ContentList.qml b/dots/quickshell/modules/launcher/ContentList.qml
deleted file mode 100644
index 7a3da96..0000000
--- a/dots/quickshell/modules/launcher/ContentList.qml
+++ /dev/null
@@ -1,189 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-import QtQuick.Controls
-
-Item {
- id: root
-
- required property PersistentProperties visibilities
- required property TextField search
- required property int padding
- required property int rounding
-
- readonly property bool showWallpapers: search.text.startsWith(`${Config.launcher.actionPrefix}wallpaper `)
- property var currentList
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
-
- clip: true
- state: showWallpapers ? "wallpapers" : "apps"
-
- states: [
- State {
- name: "apps"
-
- PropertyChanges {
- root.currentList: appList.item
- root.implicitWidth: Config.launcher.sizes.itemWidth
- root.implicitHeight: Math.max(empty.implicitHeight, appList.implicitHeight)
- appList.active: true
- }
-
- AnchorChanges {
- anchors.left: root.parent.left
- anchors.right: root.parent.right
- }
- },
- State {
- name: "wallpapers"
-
- PropertyChanges {
- root.currentList: wallpaperList.item
- root.implicitWidth: Math.max(Config.launcher.sizes.itemWidth, wallpaperList.implicitWidth)
- root.implicitHeight: Config.launcher.sizes.wallpaperHeight
- wallpaperList.active: true
- }
- }
- ]
-
- transitions: Transition {
- SequentialAnimation {
- NumberAnimation {
- target: root
- property: "opacity"
- from: 1
- to: 0
- duration: Appearance.anim.durations.small
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- PropertyAction {
- targets: [appList, wallpaperList]
- properties: "active"
- }
- ParallelAnimation {
- NumberAnimation {
- target: root
- properties: "implicitWidth,implicitHeight"
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- NumberAnimation {
- target: root
- property: "opacity"
- from: 0
- to: 1
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
- }
-
- Loader {
- id: appList
-
- active: false
- asynchronous: true
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- sourceComponent: AppList {
- search: root.search
- visibilities: root.visibilities
- }
- }
-
- Loader {
- id: wallpaperList
-
- active: false
- asynchronous: true
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
-
- sourceComponent: WallpaperList {
- search: root.search
- visibilities: root.visibilities
- }
- }
-
- Item {
- id: empty
-
- opacity: root.currentList?.count === 0 ? 1 : 0
- scale: root.currentList?.count === 0 ? 1 : 0.5
-
- implicitWidth: icon.width + text.width + Appearance.spacing.small
- implicitHeight: icon.height
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
-
- MaterialIcon {
- id: icon
-
- text: "manage_search"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.extraLarge
-
- anchors.verticalCenter: parent.verticalCenter
- }
-
- StyledText {
- id: text
-
- anchors.left: icon.right
- anchors.leftMargin: Appearance.spacing.small
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("No results")
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on scale {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- Behavior on implicitWidth {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
- }
- }
-
- Behavior on implicitHeight {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/M3Variants.qml b/dots/quickshell/modules/launcher/M3Variants.qml
deleted file mode 100644
index a4b797a..0000000
--- a/dots/quickshell/modules/launcher/M3Variants.qml
+++ /dev/null
@@ -1,91 +0,0 @@
-pragma Singleton
-
-import "root:/utils/scripts/fuzzysort.js" as Fuzzy
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property list list: [
- Variant {
- variant: "vibrant"
- icon: "sentiment_very_dissatisfied"
- name: "Vibrant"
- description: "A high chroma palette. The primary palette's chroma is at maximum."
- },
- Variant {
- variant: "tonalspot"
- icon: "android"
- name: "Tonal Spot"
- description: "Default for Material theme colours. A pastel palette with a low chroma."
- },
- Variant {
- variant: "expressive"
- icon: "compare_arrows"
- name: "Expressive"
- description: "A medium chroma palette. The primary palette's hue is different from the seed colour, for variety."
- },
- Variant {
- variant: "fidelity"
- icon: "compare"
- name: "Fidelity"
- description: "Matches the seed colour, even if the seed colour is very bright (high chroma)."
- },
- Variant {
- variant: "content"
- icon: "sentiment_calm"
- name: "Content"
- description: "Almost identical to fidelity."
- },
- Variant {
- variant: "fruitsalad"
- icon: "nutrition"
- name: "Fruit Salad"
- description: "A playful theme - the seed colour's hue does not appear in the theme."
- },
- Variant {
- variant: "rainbow"
- icon: "looks"
- name: "Rainbow"
- description: "A playful theme - the seed colour's hue does not appear in the theme."
- },
- Variant {
- variant: "neutral"
- icon: "contrast"
- name: "Neutral"
- description: "Close to grayscale, a hint of chroma."
- },
- Variant {
- variant: "monochrome"
- icon: "filter_b_and_w"
- name: "Monochrome"
- description: "All colours are grayscale, no chroma."
- }
- ]
-
- readonly property list preppedVariants: list.map(v => ({
- name: Fuzzy.prepare(v.variant),
- variant: v
- }))
-
- function fuzzyQuery(search: string): var {
- return Fuzzy.go(search.slice(`${Config.launcher.actionPrefix}variant `.length), preppedVariants, {
- all: true,
- key: "name"
- }).map(r => r.obj.variant);
- }
-
- component Variant: QtObject {
- required property string variant
- required property string icon
- required property string name
- required property string description
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Quickshell.execDetached(["caelestia", "scheme", "set", "-v", variant]);
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/SchemeItem.qml b/dots/quickshell/modules/launcher/SchemeItem.qml
deleted file mode 100644
index df635f5..0000000
--- a/dots/quickshell/modules/launcher/SchemeItem.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-
-Item {
- id: root
-
- required property Schemes.Scheme modelData
- required property var list
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- root.modelData?.onClicked(root.list);
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- StyledRect {
- id: preview
-
- anchors.verticalCenter: parent.verticalCenter
-
- border.width: 1
- border.color: Qt.alpha(`#${root.modelData?.colours?.outline}`, 0.5)
-
- color: `#${root.modelData?.colours?.surface}`
- radius: Appearance.rounding.full
- implicitWidth: parent.height * 0.8
- implicitHeight: parent.height * 0.8
-
- Item {
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.right: parent.right
-
- implicitWidth: parent.implicitWidth / 2
- clip: true
-
- StyledRect {
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.right: parent.right
-
- implicitWidth: preview.implicitWidth
- color: `#${root.modelData?.colours?.primary}`
- radius: Appearance.rounding.full
- }
- }
- }
-
- Column {
- anchors.left: preview.right
- anchors.leftMargin: Appearance.spacing.normal
- anchors.verticalCenter: parent.verticalCenter
-
- width: parent.width - preview.width
- spacing: 0
-
- StyledText {
- id: name
-
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- id: comment
-
- text: root.modelData?.flavour ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
-
- elide: Text.ElideRight
- width: parent.width - Appearance.rounding.normal * 2
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/Schemes.qml b/dots/quickshell/modules/launcher/Schemes.qml
deleted file mode 100644
index abdaaf2..0000000
--- a/dots/quickshell/modules/launcher/Schemes.qml
+++ /dev/null
@@ -1,67 +0,0 @@
-pragma Singleton
-
-import "root:/utils/scripts/fuzzysort.js" as Fuzzy
-import "root:/config"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property list preppedSchemes: schemes.instances.map(s => ({
- name: Fuzzy.prepare(s.name),
- flavour: Fuzzy.prepare(s.flavour),
- scheme: s
- }))
-
- function fuzzyQuery(search: string): var {
- return Fuzzy.go(search.slice(`${Config.launcher.actionPrefix}scheme `.length), preppedSchemes, {
- all: true,
- keys: ["name", "flavour"],
- scoreFn: r => r[0].score > 0 ? r[0].score * 0.9 + r[1].score * 0.1 : 0
- }).map(r => r.obj.scheme);
- }
-
- Variants {
- id: schemes
-
- Scheme {}
- }
-
- Process {
- id: getSchemes
-
- running: true
- command: ["caelestia", "scheme", "list"]
- stdout: StdioCollector {
- onStreamFinished: {
- const schemeData = JSON.parse(text);
- const list = Object.entries(schemeData).map(([name, f]) => Object.entries(f).map(([flavour, colours]) => ({
- name,
- flavour,
- colours
- })));
-
- const flat = [];
- for (const s of list)
- for (const f of s)
- flat.push(f);
-
- schemes.model = flat;
- }
- }
- }
-
- component Scheme: QtObject {
- required property var modelData
- readonly property string name: modelData.name
- readonly property string flavour: modelData.flavour
- readonly property var colours: modelData.colours
-
- function onClicked(list: AppList): void {
- list.visibilities.launcher = false;
- Quickshell.execDetached(["caelestia", "scheme", "set", "-n", name, "-f", flavour]);
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/VariantItem.qml b/dots/quickshell/modules/launcher/VariantItem.qml
deleted file mode 100644
index 2b5ae2e..0000000
--- a/dots/quickshell/modules/launcher/VariantItem.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Item {
- id: root
-
- required property M3Variants.Variant modelData
- required property var list
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- root.modelData?.onClicked(root.list);
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- MaterialIcon {
- id: icon
-
- text: root.modelData?.icon ?? ""
- font.pointSize: Appearance.font.size.extraLarge
-
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Item {
- anchors.left: icon.right
- anchors.leftMargin: Appearance.spacing.larger
- anchors.verticalCenter: icon.verticalCenter
-
- implicitWidth: parent.width - icon.width
- implicitHeight: name.implicitHeight + desc.implicitHeight
-
- StyledText {
- id: name
-
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- id: desc
-
- text: root.modelData?.description ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.alpha(Colours.palette.m3outline, true)
-
- elide: Text.ElideRight
- width: root.width - icon.width - Appearance.rounding.normal * 2
-
- anchors.top: name.bottom
- }
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/WallpaperItem.qml b/dots/quickshell/modules/launcher/WallpaperItem.qml
deleted file mode 100644
index 862e910..0000000
--- a/dots/quickshell/modules/launcher/WallpaperItem.qml
+++ /dev/null
@@ -1,109 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-import QtQuick.Effects
-
-StyledRect {
- id: root
-
- required property Wallpapers.Wallpaper modelData
- required property PersistentProperties visibilities
-
- scale: 0.5
- opacity: 0
- z: PathView.z ?? 0
-
- Component.onCompleted: {
- scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0);
- opacity = Qt.binding(() => PathView.onPath ? 1 : 0);
- }
-
- implicitWidth: image.width + Appearance.padding.larger * 2
- implicitHeight: image.height + label.height + Appearance.spacing.small / 2 + Appearance.padding.large + Appearance.padding.normal
-
- StateLayer {
- radius: Appearance.rounding.normal
-
- function onClicked(): void {
- Wallpapers.setWallpaper(root.modelData.path);
- root.visibilities.launcher = false;
- }
- }
-
- CachingImage {
- id: image
-
- anchors.horizontalCenter: parent.horizontalCenter
- y: Appearance.padding.large
-
- visible: false
- path: root.modelData.path
- smooth: !root.PathView.view.moving
-
- width: Config.launcher.sizes.wallpaperWidth
- height: width / 16 * 9
- }
-
- Rectangle {
- id: mask
-
- layer.enabled: true
- layer.smooth: true
- visible: false
- anchors.fill: image
- radius: Appearance.rounding.normal
- }
-
- RectangularShadow {
- opacity: root.PathView.isCurrentItem ? 0.7 : 0
- anchors.fill: mask
- radius: mask.radius
- color: Colours.palette.m3shadow
- blur: 10
- spread: 3
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- MultiEffect {
- anchors.fill: image
- source: image
- maskEnabled: true
- maskSource: mask
- maskSpreadAtMin: 1
- maskThresholdMin: 0.5
- }
-
- StyledText {
- id: label
-
- anchors.top: image.bottom
- anchors.topMargin: Appearance.spacing.small / 2
- anchors.horizontalCenter: parent.horizontalCenter
-
- width: image.width - Appearance.padding.normal * 2
- horizontalAlignment: Text.AlignHCenter
- elide: Text.ElideRight
- renderType: Text.QtRendering
- text: root.modelData.name
- font.pointSize: Appearance.font.size.normal
- }
-
- Behavior on scale {
- Anim {}
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
-}
diff --git a/dots/quickshell/modules/launcher/WallpaperList.qml b/dots/quickshell/modules/launcher/WallpaperList.qml
deleted file mode 100644
index fd82a2b..0000000
--- a/dots/quickshell/modules/launcher/WallpaperList.qml
+++ /dev/null
@@ -1,79 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-import QtQuick.Controls
-
-PathView {
- id: root
-
- required property TextField search
- required property PersistentProperties visibilities
- readonly property int numItems: {
- const screenWidth = QsWindow.window?.screen.width * 0.8;
- if (!screenWidth)
- return 0;
- const itemWidth = Config.launcher.sizes.wallpaperWidth * 0.8;
- const max = Config.launcher.maxWallpapers;
- if (max * itemWidth > screenWidth) {
- const items = Math.floor(screenWidth / itemWidth);
- return items > 1 && items % 2 === 0 ? items - 1 : items;
- }
- return max;
- }
-
- model: ScriptModel {
- readonly property string search: root.search.text.split(" ").slice(1).join(" ")
-
- values: {
- const list = Wallpapers.fuzzyQuery(search);
- if (list.length > 1 && list.length % 2 === 0)
- list.length -= 1; // Always show odd number
- return list;
- }
- onValuesChanged: root.currentIndex = search ? 0 : values.findIndex(w => w.path === Wallpapers.actualCurrent)
- }
-
- Component.onCompleted: currentIndex = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent)
- Component.onDestruction: Wallpapers.stopPreview()
-
- onCurrentItemChanged: {
- if (currentItem)
- Wallpapers.preview(currentItem.modelData.path);
- }
-
- implicitWidth: Math.min(numItems, count) * (Config.launcher.sizes.wallpaperWidth * 0.8 + Appearance.padding.larger * 2)
- pathItemCount: numItems
- cacheItemCount: 4
-
- snapMode: PathView.SnapToItem
- preferredHighlightBegin: 0.5
- preferredHighlightEnd: 0.5
- highlightRangeMode: PathView.StrictlyEnforceRange
-
- delegate: WallpaperItem {
- visibilities: root.visibilities
- }
-
- path: Path {
- startY: root.height / 2
-
- PathAttribute {
- name: "z"
- value: 0
- }
- PathLine {
- x: root.width / 2
- relativeY: 0
- }
- PathAttribute {
- name: "z"
- value: 1
- }
- PathLine {
- x: root.width
- relativeY: 0
- }
- }
-}
diff --git a/dots/quickshell/modules/launcher/Wrapper.qml b/dots/quickshell/modules/launcher/Wrapper.qml
deleted file mode 100644
index 86c8b95..0000000
--- a/dots/quickshell/modules/launcher/Wrapper.qml
+++ /dev/null
@@ -1,55 +0,0 @@
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property PersistentProperties visibilities
-
- visible: height > 0
- implicitHeight: 0
- implicitWidth: content.implicitWidth
-
- states: State {
- name: "visible"
- when: root.visibilities.launcher
-
- PropertyChanges {
- root.implicitHeight: content.implicitHeight
- }
- }
-
- transitions: [
- Transition {
- from: ""
- to: "visible"
-
- NumberAnimation {
- target: root
- property: "implicitHeight"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- },
- Transition {
- from: "visible"
- to: ""
-
- NumberAnimation {
- target: root
- property: "implicitHeight"
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- ]
-
- Content {
- id: content
-
- visibilities: root.visibilities
- }
-}
diff --git a/dots/quickshell/modules/notifications/Background.qml b/dots/quickshell/modules/notifications/Background.qml
deleted file mode 100644
index 4a38510..0000000
--- a/dots/quickshell/modules/notifications/Background.qml
+++ /dev/null
@@ -1,66 +0,0 @@
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-import QtQuick.Shapes
-
-ShapePath {
- id: root
-
- required property Wrapper wrapper
- readonly property real rounding: Config.border.rounding
- readonly property bool flatten: wrapper.height < rounding * 2
- readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
- property real fullHeightRounding: wrapper.height >= QsWindow.window?.height - Config.border.thickness * 2 ? -rounding : rounding
-
- strokeWidth: -1
- fillColor: Config.border.colour
-
- PathLine {
- relativeX: -(root.wrapper.width + root.rounding)
- relativeY: 0
- }
- PathArc {
- relativeX: root.rounding
- relativeY: root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- }
- PathLine {
- relativeX: 0
- relativeY: root.wrapper.height - root.roundingY * 2
- }
- PathArc {
- relativeX: root.fullHeightRounding
- relativeY: root.roundingY
- radiusX: Math.abs(root.fullHeightRounding)
- radiusY: Math.min(root.rounding, root.wrapper.height)
- direction: root.fullHeightRounding < 0 ? PathArc.Clockwise : PathArc.Counterclockwise
- }
- PathLine {
- relativeX: root.wrapper.height > 0 ? root.wrapper.width - root.rounding - root.fullHeightRounding : root.wrapper.width
- relativeY: 0
- }
- PathArc {
- relativeX: root.rounding
- relativeY: root.rounding
- radiusX: root.rounding
- radiusY: root.rounding
- }
-
- Behavior on fillColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on fullHeightRounding {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/modules/notifications/Content.qml b/dots/quickshell/modules/notifications/Content.qml
deleted file mode 100644
index 6983b95..0000000
--- a/dots/quickshell/modules/notifications/Content.qml
+++ /dev/null
@@ -1,162 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-
-Item {
- id: root
-
- readonly property int padding: Appearance.padding.large
-
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.right: parent.right
-
- implicitWidth: Config.notifs.sizes.width + padding * 2
- implicitHeight: {
- const count = list.count;
- if (count === 0)
- return 0;
-
- let height = (count - 1) * Appearance.spacing.smaller;
- for (let i = 0; i < count; i++)
- height += list.itemAtIndex(i)?.nonAnimHeight ?? 0;
-
- const screen = QsWindow.window?.screen;
- const visibilities = Visibilities.screens[screen];
- const panel = Visibilities.panels[screen];
- if (visibilities && panel) {
- if (visibilities.osd) {
- const h = panel.osd.y - Config.border.rounding * 2;
- if (height > h)
- height = h;
- }
-
- if (visibilities.session) {
- const h = panel.session.y - Config.border.rounding * 2;
- if (height > h)
- height = h;
- }
- }
-
- return Math.min((screen?.height ?? 0) - Config.border.thickness * 2, height + padding * 2);
- }
-
- ClippingWrapperRectangle {
- anchors.fill: parent
- anchors.margins: root.padding
-
- color: "transparent"
- radius: Appearance.rounding.normal
-
- ListView {
- id: list
-
- model: ScriptModel {
- values: [...Notifs.popups].reverse()
- }
-
- anchors.fill: parent
-
- orientation: Qt.Vertical
- spacing: 0
- cacheBuffer: QsWindow.window?.screen.height ?? 0
-
- delegate: Item {
- id: wrapper
-
- required property Notifs.Notif modelData
- required property int index
- readonly property alias nonAnimHeight: notif.nonAnimHeight
- property int idx
-
- onIndexChanged: {
- if (index !== -1)
- idx = index;
- }
-
- implicitWidth: notif.implicitWidth
- implicitHeight: notif.implicitHeight + (idx === 0 ? 0 : Appearance.spacing.smaller)
-
- ListView.onRemove: removeAnim.start()
-
- SequentialAnimation {
- id: removeAnim
-
- PropertyAction {
- target: wrapper
- property: "ListView.delayRemove"
- value: true
- }
- PropertyAction {
- target: wrapper
- property: "enabled"
- value: false
- }
- PropertyAction {
- target: wrapper
- property: "implicitHeight"
- value: 0
- }
- PropertyAction {
- target: wrapper
- property: "z"
- value: 1
- }
- Anim {
- target: notif
- property: "x"
- to: (notif.x >= 0 ? Config.notifs.sizes.width : -Config.notifs.sizes.width) * 2
- duration: Appearance.anim.durations.normal
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- PropertyAction {
- target: wrapper
- property: "ListView.delayRemove"
- value: false
- }
- }
-
- ClippingRectangle {
- anchors.top: parent.top
- anchors.topMargin: wrapper.idx === 0 ? 0 : Appearance.spacing.smaller
-
- color: "transparent"
- radius: notif.radius
- implicitWidth: notif.implicitWidth
- implicitHeight: notif.implicitHeight
-
- Notification {
- id: notif
-
- modelData: wrapper.modelData
- }
- }
- }
-
- move: Transition {
- Anim {
- property: "y"
- }
- }
-
- displaced: Transition {
- Anim {
- property: "y"
- }
- }
- }
- }
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
-}
diff --git a/dots/quickshell/modules/notifications/Notification.qml b/dots/quickshell/modules/notifications/Notification.qml
deleted file mode 100644
index 6550e28..0000000
--- a/dots/quickshell/modules/notifications/Notification.qml
+++ /dev/null
@@ -1,494 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Widgets
-import Quickshell.Services.Notifications
-import QtQuick
-import QtQuick.Layouts
-
-StyledRect {
- id: root
-
- required property Notifs.Notif modelData
- readonly property bool hasImage: modelData.image.length > 0
- readonly property bool hasAppIcon: modelData.appIcon.length > 0
- readonly property int nonAnimHeight: summary.implicitHeight + (root.expanded ? appName.height + body.height + actions.height + actions.anchors.topMargin : bodyPreview.height) + inner.anchors.margins * 2
- property bool expanded
-
- color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3secondaryContainer : Colours.palette.m3surfaceContainer
- radius: Appearance.rounding.normal
- implicitWidth: Config.notifs.sizes.width
- implicitHeight: inner.implicitHeight
-
- x: Config.notifs.sizes.width
- Component.onCompleted: x = 0
-
- RetainableLock {
- object: root.modelData.notification
- locked: true
- }
-
- MouseArea {
- property int startY
-
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: pressed ? Qt.ClosedHandCursor : undefined
- acceptedButtons: Qt.LeftButton | Qt.MiddleButton
- preventStealing: true
-
- onEntered: root.modelData.timer.stop()
- onExited: root.modelData.timer.start()
-
- drag.target: parent
- drag.axis: Drag.XAxis
-
- onPressed: event => {
- startY = event.y;
- if (event.button === Qt.MiddleButton)
- root.modelData.notification.dismiss();
- }
- onReleased: event => {
- if (Math.abs(root.x) < Config.notifs.sizes.width * Config.notifs.clearThreshold)
- root.x = 0;
- else
- root.modelData.popup = false;
- }
- onPositionChanged: event => {
- if (pressed) {
- const diffY = event.y - startY;
- if (Math.abs(diffY) > Config.notifs.expandThreshold)
- root.expanded = diffY > 0;
- }
- }
- onClicked: event => {
- if (!Config.notifs.actionOnClick || event.button !== Qt.LeftButton)
- return;
-
- const actions = root.modelData.actions;
- if (actions?.length === 1)
- actions[0].invoke();
- }
- }
-
- Behavior on x {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
- }
- }
-
- Item {
- id: inner
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.margins: Appearance.padding.normal
-
- implicitHeight: root.nonAnimHeight
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- Loader {
- id: image
-
- active: root.hasImage
- asynchronous: true
-
- anchors.left: parent.left
- anchors.top: parent.top
- width: Config.notifs.sizes.image
- height: Config.notifs.sizes.image
- visible: root.hasImage || root.hasAppIcon
-
- sourceComponent: ClippingRectangle {
- radius: Appearance.rounding.full
- implicitWidth: Config.notifs.sizes.image
- implicitHeight: Config.notifs.sizes.image
-
- Image {
- anchors.fill: parent
- source: Qt.resolvedUrl(root.modelData.image)
- fillMode: Image.PreserveAspectCrop
- cache: false
- asynchronous: true
- }
- }
- }
-
- Loader {
- id: appIcon
-
- active: root.hasAppIcon || !root.hasImage
- asynchronous: true
-
- anchors.horizontalCenter: root.hasImage ? undefined : image.horizontalCenter
- anchors.verticalCenter: root.hasImage ? undefined : image.verticalCenter
- anchors.right: root.hasImage ? image.right : undefined
- anchors.bottom: root.hasImage ? image.bottom : undefined
-
- sourceComponent: StyledRect {
- radius: Appearance.rounding.full
- color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3surfaceContainerHighest : Colours.palette.m3tertiaryContainer
- implicitWidth: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
- implicitHeight: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
-
- Loader {
- id: icon
-
- active: root.hasAppIcon
- asynchronous: true
-
- anchors.centerIn: parent
- visible: !root.modelData.appIcon.endsWith("symbolic")
-
- width: Math.round(parent.width * 0.6)
- height: Math.round(parent.width * 0.6)
-
- sourceComponent: IconImage {
- implicitSize: Math.round(parent.width * 0.6)
- source: Quickshell.iconPath(root.modelData.appIcon)
- asynchronous: true
- }
- }
-
- Loader {
- active: root.modelData.appIcon.endsWith("symbolic")
- asynchronous: true
- anchors.fill: icon
-
- sourceComponent: Colouriser {
- source: icon
- colorizationColor: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer
- }
- }
-
- Loader {
- active: !root.hasAppIcon
- asynchronous: true
- anchors.centerIn: parent
-
- sourceComponent: MaterialIcon {
- text: {
- const summary = root.modelData.summary.toLowerCase();
- if (summary.includes("reboot"))
- return "restart_alt";
- if (summary.includes("recording"))
- return "screen_record";
- if (summary.includes("battery"))
- return "power";
- if (summary.includes("screenshot"))
- return "screenshot_monitor";
- if (summary.includes("welcome"))
- return "waving_hand";
- if (summary.includes("time") || summary.includes("a break"))
- return "schedule";
- if (summary.includes("installed"))
- return "download";
- if (summary.includes("update"))
- return "update";
- if (summary.startsWith("file"))
- return "folder_copy";
- if (summary.startsWith("unable to"))
- return "deployed_code_alert";
- if (root.modelData.urgency === NotificationUrgency.Critical)
- return "release_alert";
- return "chat";
- }
-
- color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer
- font.pointSize: Appearance.font.size.large
- }
- }
- }
- }
-
- StyledText {
- id: appName
-
- anchors.top: parent.top
- anchors.left: image.right
- anchors.leftMargin: Appearance.spacing.smaller
-
- animate: true
- text: appNameMetrics.elidedText
- maximumLineCount: 1
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
-
- opacity: root.expanded ? 1 : 0
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- TextMetrics {
- id: appNameMetrics
-
- text: root.modelData.appName
- font.family: appName.font.family
- font.pointSize: appName.font.pointSize
- elide: Text.ElideRight
- elideWidth: expandBtn.x - time.width - timeSep.width - summary.x - Appearance.spacing.small * 3
- }
-
- StyledText {
- id: summary
-
- anchors.top: parent.top
- anchors.left: image.right
- anchors.leftMargin: Appearance.spacing.smaller
-
- animate: true
- text: summaryMetrics.elidedText
- maximumLineCount: 1
- height: implicitHeight
-
- states: State {
- name: "expanded"
- when: root.expanded
-
- PropertyChanges {
- summary.maximumLineCount: undefined
- }
-
- AnchorChanges {
- target: summary
- anchors.top: appName.bottom
- }
- }
-
- transitions: Transition {
- PropertyAction {
- target: summary
- property: "maximumLineCount"
- }
- AnchorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on height {
- Anim {}
- }
- }
-
- TextMetrics {
- id: summaryMetrics
-
- text: root.modelData.summary
- font.family: summary.font.family
- font.pointSize: summary.font.pointSize
- elide: Text.ElideRight
- elideWidth: expandBtn.x - time.width - timeSep.width - summary.x - Appearance.spacing.small * 3
- }
-
- StyledText {
- id: timeSep
-
- anchors.top: parent.top
- anchors.left: summary.right
- anchors.leftMargin: Appearance.spacing.small
-
- text: "•"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
-
- states: State {
- name: "expanded"
- when: root.expanded
-
- AnchorChanges {
- target: timeSep
- anchors.left: appName.right
- }
- }
-
- transitions: Transition {
- AnchorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- StyledText {
- id: time
-
- anchors.top: parent.top
- anchors.left: timeSep.right
- anchors.leftMargin: Appearance.spacing.small
-
- animate: true
- horizontalAlignment: Text.AlignLeft
- text: root.modelData.timeStr
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- }
-
- Item {
- id: expandBtn
-
- anchors.right: parent.right
- anchors.top: parent.top
-
- implicitWidth: expandIcon.height
- implicitHeight: expandIcon.height
-
- StateLayer {
- radius: Appearance.rounding.full
-
- function onClicked() {
- root.expanded = !root.expanded;
- }
- }
-
- MaterialIcon {
- id: expandIcon
-
- anchors.centerIn: parent
-
- animate: true
- text: root.expanded ? "expand_less" : "expand_more"
- font.pointSize: Appearance.font.size.normal
- }
- }
-
- StyledText {
- id: bodyPreview
-
- anchors.left: summary.left
- anchors.right: expandBtn.left
- anchors.top: summary.bottom
- anchors.rightMargin: Appearance.spacing.small
-
- animate: true
- textFormat: Text.MarkdownText
- text: bodyPreviewMetrics.elidedText
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
-
- opacity: root.expanded ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- TextMetrics {
- id: bodyPreviewMetrics
-
- text: root.modelData.body
- font.family: bodyPreview.font.family
- font.pointSize: bodyPreview.font.pointSize
- elide: Text.ElideRight
- elideWidth: bodyPreview.width
- }
-
- StyledText {
- id: body
-
- anchors.left: summary.left
- anchors.right: expandBtn.left
- anchors.top: summary.bottom
- anchors.rightMargin: Appearance.spacing.small
-
- animate: true
- textFormat: Text.MarkdownText
- text: root.modelData.body
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
-
- opacity: root.expanded ? 1 : 0
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- RowLayout {
- id: actions
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: body.bottom
- anchors.topMargin: Appearance.spacing.small
-
- spacing: Appearance.spacing.smaller
-
- opacity: root.expanded ? 1 : 0
-
- Behavior on opacity {
- Anim {}
- }
-
- Repeater {
- model: root.modelData.actions
-
- delegate: StyledRect {
- id: action
-
- required property NotificationAction modelData
-
- radius: Appearance.rounding.full
- color: Colours.palette.m3surfaceContainerHigh
-
- Layout.preferredWidth: actionText.width + Appearance.padding.normal * 2
- Layout.preferredHeight: actionText.height + Appearance.padding.small * 2
- implicitWidth: actionText.width + Appearance.padding.normal * 2
- implicitHeight: actionText.height + Appearance.padding.small * 2
-
- StateLayer {
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- action.modelData.invoke();
- }
- }
-
- StyledText {
- id: actionText
-
- anchors.centerIn: parent
- text: actionTextMetrics.elidedText
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- }
-
- TextMetrics {
- id: actionTextMetrics
-
- text: modelData.text
- font.family: actionText.font.family
- font.pointSize: actionText.font.pointSize
- elide: Text.ElideRight
- elideWidth: {
- const numActions = root.modelData.actions.length;
- return (inner.width - actions.spacing * (numActions - 1)) / numActions - Appearance.padding.normal * 2;
- }
- }
- }
- }
- }
- }
-
- component Anim: NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
-}
diff --git a/dots/quickshell/modules/notifications/Wrapper.qml b/dots/quickshell/modules/notifications/Wrapper.qml
deleted file mode 100644
index 27b9219..0000000
--- a/dots/quickshell/modules/notifications/Wrapper.qml
+++ /dev/null
@@ -1,14 +0,0 @@
-import "root:/config"
-import QtQuick
-
-Item {
- id: root
-
- visible: height > 0
- implicitHeight: content.implicitHeight
- implicitWidth: content.implicitWidth
-
- Content {
- id: content
- }
-}
diff --git a/dots/quickshell/modules/osd/Background.qml b/dots/quickshell/modules/osd/Background.qml
deleted file mode 100644
index 12cce6a..0000000
--- a/dots/quickshell/modules/osd/Background.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Shapes
-
-ShapePath {
- id: root
-
- required property Wrapper wrapper
- readonly property real rounding: Config.border.rounding
- readonly property bool flatten: wrapper.width < rounding * 2
- readonly property real roundingX: flatten ? wrapper.width / 2 : rounding
-
- strokeWidth: -1
- fillColor: Config.border.colour
-
- PathArc {
- relativeX: -root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- }
- PathLine {
- relativeX: -(root.wrapper.width - root.roundingX * 2)
- relativeY: 0
- }
- PathArc {
- relativeX: -root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: root.wrapper.height - root.rounding * 2
- }
- PathArc {
- relativeX: root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: root.wrapper.width - root.roundingX * 2
- relativeY: 0
- }
- PathArc {
- relativeX: root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- }
-
- Behavior on fillColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/modules/osd/Content.qml b/dots/quickshell/modules/osd/Content.qml
deleted file mode 100644
index 4bd43af..0000000
--- a/dots/quickshell/modules/osd/Content.qml
+++ /dev/null
@@ -1,43 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Column {
- id: root
-
- required property Brightness.Monitor monitor
-
- padding: Appearance.padding.large
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
-
- spacing: Appearance.spacing.normal
-
- VerticalSlider {
- icon: {
- if (Audio.muted)
- return "no_sound";
- if (value >= 0.5)
- return "volume_up";
- if (value > 0)
- return "volume_down";
- return "volume_mute";
- }
- value: Audio.volume
- onMoved: Audio.setVolume(value)
-
- implicitWidth: Config.osd.sizes.sliderWidth
- implicitHeight: Config.osd.sizes.sliderHeight
- }
-
- VerticalSlider {
- icon: `brightness_${(Math.round(value * 6) + 1)}`
- value: root.monitor?.brightness ?? 0
- onMoved: root.monitor?.setBrightness(value)
-
- implicitWidth: Config.osd.sizes.sliderWidth
- implicitHeight: Config.osd.sizes.sliderHeight
- }
-}
diff --git a/dots/quickshell/modules/osd/Interactions.qml b/dots/quickshell/modules/osd/Interactions.qml
deleted file mode 100644
index fa75aa0..0000000
--- a/dots/quickshell/modules/osd/Interactions.qml
+++ /dev/null
@@ -1,48 +0,0 @@
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Scope {
- id: root
-
- required property ShellScreen screen
- required property PersistentProperties visibilities
- required property bool hovered
- readonly property Brightness.Monitor monitor: Brightness.getMonitorForScreen(screen)
-
- function show(): void {
- root.visibilities.osd = true;
- timer.restart();
- }
-
- Connections {
- target: Audio
-
- function onMutedChanged(): void {
- root.show();
- }
-
- function onVolumeChanged(): void {
- root.show();
- }
- }
-
- Connections {
- target: root.monitor
-
- function onBrightnessChanged(): void {
- root.show();
- }
- }
-
- Timer {
- id: timer
-
- interval: Config.osd.hideDelay
- onTriggered: {
- if (!root.hovered)
- root.visibilities.osd = false;
- }
- }
-}
diff --git a/dots/quickshell/modules/osd/Wrapper.qml b/dots/quickshell/modules/osd/Wrapper.qml
deleted file mode 100644
index 2969002..0000000
--- a/dots/quickshell/modules/osd/Wrapper.qml
+++ /dev/null
@@ -1,57 +0,0 @@
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property bool visibility
-
- visible: width > 0
- implicitWidth: 0
- implicitHeight: content.implicitHeight
-
- states: State {
- name: "visible"
- when: root.visibility
-
- PropertyChanges {
- root.implicitWidth: content.implicitWidth
- }
- }
-
- transitions: [
- Transition {
- from: ""
- to: "visible"
-
- NumberAnimation {
- target: root
- property: "implicitWidth"
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- },
- Transition {
- from: "visible"
- to: ""
-
- NumberAnimation {
- target: root
- property: "implicitWidth"
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- ]
-
- Content {
- id: content
-
- monitor: Brightness.getMonitorForScreen(root.screen)
- }
-}
diff --git a/dots/quickshell/modules/session/Background.qml b/dots/quickshell/modules/session/Background.qml
deleted file mode 100644
index 12cce6a..0000000
--- a/dots/quickshell/modules/session/Background.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Shapes
-
-ShapePath {
- id: root
-
- required property Wrapper wrapper
- readonly property real rounding: Config.border.rounding
- readonly property bool flatten: wrapper.width < rounding * 2
- readonly property real roundingX: flatten ? wrapper.width / 2 : rounding
-
- strokeWidth: -1
- fillColor: Config.border.colour
-
- PathArc {
- relativeX: -root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- }
- PathLine {
- relativeX: -(root.wrapper.width - root.roundingX * 2)
- relativeY: 0
- }
- PathArc {
- relativeX: -root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: root.wrapper.height - root.rounding * 2
- }
- PathArc {
- relativeX: root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: root.wrapper.width - root.roundingX * 2
- relativeY: 0
- }
- PathArc {
- relativeX: root.roundingX
- relativeY: root.rounding
- radiusX: Math.min(root.rounding, root.wrapper.width)
- radiusY: root.rounding
- }
-
- Behavior on fillColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/modules/session/Content.qml b/dots/quickshell/modules/session/Content.qml
deleted file mode 100644
index f6b1258..0000000
--- a/dots/quickshell/modules/session/Content.qml
+++ /dev/null
@@ -1,119 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Column {
- id: root
-
- required property PersistentProperties visibilities
-
- padding: Appearance.padding.large
-
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
-
- spacing: Appearance.spacing.large
-
- SessionButton {
- id: logout
-
- icon: "logout"
- command: ["sh", "-c", "(uwsm stop | grep -q 'Compositor is not running' && loginctl terminate-user $USER) || uwsm stop"]
-
- KeyNavigation.down: shutdown
-
- Connections {
- target: root.visibilities
-
- function onSessionChanged(): void {
- if (root.visibilities.session)
- logout.focus = true;
- }
- }
- }
-
- SessionButton {
- id: shutdown
-
- icon: "power_settings_new"
- command: ["systemctl", "poweroff"]
-
- KeyNavigation.up: logout
- KeyNavigation.down: hibernate
- }
-
- AnimatedImage {
- width: Config.session.sizes.button
- height: Config.session.sizes.button
- sourceSize.width: width
- sourceSize.height: height
-
- playing: visible
- asynchronous: true
- speed: 0.7
- source: "root:/assets/kurukuru.gif"
- }
-
- SessionButton {
- id: hibernate
-
- icon: "downloading"
- command: ["systemctl", "hibernate"]
-
- KeyNavigation.up: shutdown
- KeyNavigation.down: reboot
- }
-
- SessionButton {
- id: reboot
-
- icon: "cached"
- command: ["systemctl", "reboot"]
-
- KeyNavigation.up: hibernate
- }
-
- component SessionButton: StyledRect {
- id: button
-
- required property string icon
- required property list command
-
- implicitWidth: Config.session.sizes.button
- implicitHeight: Config.session.sizes.button
-
- radius: Appearance.rounding.large
- color: button.activeFocus ? Colours.palette.m3secondaryContainer : Colours.palette.m3surfaceContainer
-
- Keys.onEnterPressed: proc.startDetached()
- Keys.onReturnPressed: proc.startDetached()
- Keys.onEscapePressed: root.visibilities.session = false
-
- Process {
- id: proc
-
- command: button.command
- }
-
- StateLayer {
- radius: parent.radius
-
- function onClicked(): void {
- proc.startDetached();
- }
- }
-
- MaterialIcon {
- anchors.centerIn: parent
-
- text: button.icon
- color: button.activeFocus ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
- font.pointSize: Appearance.font.size.extraLarge
- }
- }
-}
diff --git a/dots/quickshell/modules/session/Wrapper.qml b/dots/quickshell/modules/session/Wrapper.qml
deleted file mode 100644
index db7105e..0000000
--- a/dots/quickshell/modules/session/Wrapper.qml
+++ /dev/null
@@ -1,56 +0,0 @@
-import "root:/services"
-import "root:/config"
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property PersistentProperties visibilities
-
- visible: width > 0
- implicitWidth: 0
- implicitHeight: content.implicitHeight
-
- states: State {
- name: "visible"
- when: root.visibilities.session
-
- PropertyChanges {
- root.implicitWidth: content.implicitWidth
- }
- }
-
- transitions: [
- Transition {
- from: ""
- to: "visible"
-
- NumberAnimation {
- target: root
- property: "implicitWidth"
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- },
- Transition {
- from: "visible"
- to: ""
-
- NumberAnimation {
- target: root
- property: "implicitWidth"
- duration: root.visibilities.osd ? Appearance.anim.durations.expressiveFastSpatial : Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: root.visibilities.osd ? Appearance.anim.curves.expressiveFastSpatial : Appearance.anim.curves.emphasized
- }
- }
- ]
-
- Content {
- id: content
-
- visibilities: root.visibilities
- }
-}
diff --git a/dots/quickshell/run.fish b/dots/quickshell/run.fish
deleted file mode 100755
index ada4152..0000000
--- a/dots/quickshell/run.fish
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env fish
-
-set -l dbus 'quickshell.dbus.properties.warning = false;quickshell.dbus.dbusmenu.warning = false' # System tray dbus property errors
-set -l notifs 'quickshell.service.notifications.warning = false' # Notification server warnings on reload
-set -l sni 'quickshell.service.sni.host.warning = false' # StatusNotifierItem warnings on reload
-set -l process 'QProcess: Destroyed while process' # Long running processes on reload
-set -l cache "Cannot open: file://$XDG_CACHE_HOME/caelestia/imagecache/"
-
-qs -p (dirname (status filename)) --log-rules "$dbus;$notifs;$sni" | grep -vF -e $process -e $cache
diff --git a/dots/quickshell/services/Apps.qml b/dots/quickshell/services/Apps.qml
deleted file mode 100644
index e3ab276..0000000
--- a/dots/quickshell/services/Apps.qml
+++ /dev/null
@@ -1,37 +0,0 @@
-pragma Singleton
-
-import "root:/utils/scripts/fuzzysort.js" as Fuzzy
-import Quickshell
-import Quickshell.Io
-
-Singleton {
- id: root
-
- readonly property list list: DesktopEntries.applications.values.filter(a => !a.noDisplay).sort((a, b) => a.name.localeCompare(b.name))
- readonly property list preppedApps: list.map(a => ({
- name: Fuzzy.prepare(a.name),
- comment: Fuzzy.prepare(a.comment),
- entry: a
- }))
-
- function fuzzyQuery(search: string): var { // Idk why list doesn't work
- return Fuzzy.go(search, preppedApps, {
- all: true,
- keys: ["name", "comment"],
- scoreFn: r => r[0].score > 0 ? r[0].score * 0.9 + r[1].score * 0.1 : 0
- }).map(r => r.obj.entry);
- }
-
- function launch(entry: DesktopEntry): void {
- launchProc.entry = entry;
- launchProc.startDetached();
- }
-
- Process {
- id: launchProc
-
- property DesktopEntry entry
-
- command: ["app2unit", "--", `${entry?.id}.desktop`]
- }
-}
diff --git a/dots/quickshell/services/Audio.qml b/dots/quickshell/services/Audio.qml
deleted file mode 100644
index c91adbc..0000000
--- a/dots/quickshell/services/Audio.qml
+++ /dev/null
@@ -1,25 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Services.Pipewire
-
-Singleton {
- id: root
-
- readonly property PwNode sink: Pipewire.defaultAudioSink
- readonly property PwNode source: Pipewire.defaultAudioSource
-
- readonly property bool muted: sink?.audio?.muted ?? false
- readonly property real volume: sink?.audio?.volume ?? 0
-
- function setVolume(volume: real): void {
- if (sink?.ready && sink?.audio) {
- sink.audio.muted = false;
- sink.audio.volume = volume;
- }
- }
-
- PwObjectTracker {
- objects: [Pipewire.defaultAudioSink, Pipewire.defaultAudioSource]
- }
-}
diff --git a/dots/quickshell/services/BeatDetector.qml b/dots/quickshell/services/BeatDetector.qml
deleted file mode 100644
index 65dd88e..0000000
--- a/dots/quickshell/services/BeatDetector.qml
+++ /dev/null
@@ -1,22 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-
-Singleton {
- id: root
-
- property real bpm
-
- Process {
- running: true
- command: ["/usr/lib/caelestia/beat_detector", "--no-log", "--no-stats", "--no-visual"]
- stdout: SplitParser {
- onRead: data => {
- const match = data.match(/BPM: ([0-9]+\.[0-9])/);
- if (match)
- root.bpm = parseFloat(match[1]);
- }
- }
- }
-}
diff --git a/dots/quickshell/services/Bluetooth.qml b/dots/quickshell/services/Bluetooth.qml
deleted file mode 100644
index f5e9de1..0000000
--- a/dots/quickshell/services/Bluetooth.qml
+++ /dev/null
@@ -1,96 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- property bool powered
- property bool discovering
- readonly property list devices: []
-
- Process {
- running: true
- command: ["bluetoothctl"]
- stdout: SplitParser {
- onRead: {
- getInfo.running = true;
- getDevices.running = true;
- }
- }
- }
-
- Process {
- id: getInfo
-
- running: true
- command: ["bluetoothctl", "show"]
- stdout: StdioCollector {
- onStreamFinished: {
- root.powered = text.includes("Powered: yes");
- root.discovering = text.includes("Discovering: yes");
- }
- }
- }
-
- Process {
- id: getDevices
-
- running: true
- command: ["fish", "-c", `
- for a in (bluetoothctl devices)
- if string match -q 'Device *' $a
- bluetoothctl info $addr (string split ' ' $a)[2]
- echo
- end
- end`]
- stdout: StdioCollector {
- onStreamFinished: {
- const devices = text.trim().split("\n\n").map(d => ({
- name: d.match(/Name: (.*)/)[1],
- alias: d.match(/Alias: (.*)/)[1],
- address: d.match(/Device ([0-9A-Z:]{17})/)[1],
- icon: d.match(/Icon: (.*)/)[1],
- connected: d.includes("Connected: yes"),
- paired: d.includes("Paired: yes"),
- trusted: d.includes("Trusted: yes")
- }));
- const rDevices = root.devices;
-
- const destroyed = rDevices.filter(rd => !devices.find(d => d.address === rd.address));
- for (const device of destroyed)
- rDevices.splice(rDevices.indexOf(device), 1).forEach(d => d.destroy());
-
- for (const device of devices) {
- const match = rDevices.find(d => d.address === device.address);
- if (match) {
- match.lastIpcObject = device;
- } else {
- rDevices.push(deviceComp.createObject(root, {
- lastIpcObject: device
- }));
- }
- }
- }
- }
- }
-
- component Device: QtObject {
- required property var lastIpcObject
- readonly property string name: lastIpcObject.name
- readonly property string alias: lastIpcObject.alias
- readonly property string address: lastIpcObject.address
- readonly property string icon: lastIpcObject.icon
- readonly property bool connected: lastIpcObject.connected
- readonly property bool paired: lastIpcObject.paired
- readonly property bool trusted: lastIpcObject.trusted
- }
-
- Component {
- id: deviceComp
-
- Device {}
- }
-}
diff --git a/dots/quickshell/services/Brightness.qml b/dots/quickshell/services/Brightness.qml
deleted file mode 100644
index 3715853..0000000
--- a/dots/quickshell/services/Brightness.qml
+++ /dev/null
@@ -1,111 +0,0 @@
-pragma Singleton
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- property list ddcMonitors: []
- readonly property list monitors: variants.instances
-
- function getMonitorForScreen(screen: ShellScreen): var {
- return monitors.find(m => m.modelData === screen);
- }
-
- function increaseBrightness(): void {
- const focusedName = Hyprland.focusedMonitor.name;
- const monitor = monitors.find(m => focusedName === m.modelData.name);
- if (monitor)
- monitor.setBrightness(monitor.brightness + 0.1);
- }
-
- function decreaseBrightness(): void {
- const focusedName = Hyprland.focusedMonitor.name;
- const monitor = monitors.find(m => focusedName === m.modelData.name);
- if (monitor)
- monitor.setBrightness(monitor.brightness - 0.1);
- }
-
- reloadableId: "brightness"
-
- onMonitorsChanged: {
- ddcMonitors = [];
- ddcProc.running = true;
- }
-
- Variants {
- id: variants
-
- model: Quickshell.screens
-
- Monitor {}
- }
-
- Process {
- id: ddcProc
-
- command: ["ddcutil", "detect", "--brief"]
- stdout: StdioCollector {
- onStreamFinished: root.ddcMonitors = text.trim().split("\n\n").filter(d => d.startsWith("Display ")).map(d => ({
- model: d.match(/Monitor:.*:(.*):.*/)[1],
- busNum: d.match(/I2C bus:[ ]*\/dev\/i2c-([0-9]+)/)[1]
- }))
- }
- }
-
- Process {
- id: setProc
- }
-
- CustomShortcut {
- name: "brightnessUp"
- onPressed: root.increaseBrightness()
- }
-
- CustomShortcut {
- name: "brightnessDown"
- onPressed: root.decreaseBrightness()
- }
-
- component Monitor: QtObject {
- id: monitor
-
- required property ShellScreen modelData
- readonly property bool isDdc: root.ddcMonitors.some(m => m.model === modelData.model)
- readonly property string busNum: root.ddcMonitors.find(m => m.model === modelData.model)?.busNum ?? ""
- property real brightness
-
- readonly property Process initProc: Process {
- stdout: StdioCollector {
- onStreamFinished: {
- const [, , , current, max] = text.split(" ");
- monitor.brightness = parseInt(current) / parseInt(max);
- }
- }
- }
-
- function setBrightness(value: real): void {
- value = Math.max(0, Math.min(1, value));
- const rounded = Math.round(value * 100);
- if (Math.round(brightness * 100) === rounded)
- return;
- brightness = value;
- setProc.command = isDdc ? ["ddcutil", "-b", busNum, "setvcp", "10", rounded] : ["brightnessctl", "s", `${rounded}%`];
- setProc.startDetached();
- }
-
- onBusNumChanged: {
- initProc.command = isDdc ? ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] : ["sh", "-c", `echo "a b c $(brightnessctl g) $(brightnessctl m)"`];
- initProc.running = true;
- }
-
- Component.onCompleted: {
- initProc.command = isDdc ? ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] : ["sh", "-c", `echo "a b c $(brightnessctl g) $(brightnessctl m)"`];
- initProc.running = true;
- }
- }
-}
diff --git a/dots/quickshell/services/Cava.qml b/dots/quickshell/services/Cava.qml
deleted file mode 100644
index 3fa5083..0000000
--- a/dots/quickshell/services/Cava.qml
+++ /dev/null
@@ -1,19 +0,0 @@
-pragma Singleton
-
-import "root:/config"
-import Quickshell
-import Quickshell.Io
-
-Singleton {
- id: root
-
- property list values
-
- Process {
- running: true
- command: ["sh", "-c", `printf '[general]\nframerate=60\nbars=${Config.dashboard.visualiserBars}\n[output]\nchannels=mono\nmethod=raw\nraw_target=/dev/stdout\ndata_format=ascii\nascii_max_range=100' | cava -p /dev/stdin`]
- stdout: SplitParser {
- onRead: data => root.values = data.slice(0, -1).split(";").map(v => parseInt(v, 10))
- }
- }
-}
diff --git a/dots/quickshell/services/Colours.qml b/dots/quickshell/services/Colours.qml
deleted file mode 100644
index 20fb6aa..0000000
--- a/dots/quickshell/services/Colours.qml
+++ /dev/null
@@ -1,143 +0,0 @@
-pragma Singleton
-
-import "root:/config"
-import "root:/utils"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property list colourNames: ["rosewater", "flamingo", "pink", "mauve", "red", "maroon", "peach", "yellow", "green", "teal", "sky", "sapphire", "blue", "lavender"]
-
- property bool showPreview
- property bool endPreviewOnNextChange
- property bool light
- readonly property Colours palette: showPreview ? preview : current
- readonly property Colours current: Colours {}
- readonly property Colours preview: Colours {}
- readonly property Transparency transparency: Transparency {}
-
- function alpha(c: color, layer: bool): color {
- if (!transparency.enabled)
- return c;
- c = Qt.rgba(c.r, c.g, c.b, layer ? transparency.layers : transparency.base);
- if (layer)
- c.hsvValue = Math.max(0, Math.min(1, c.hslLightness + (light ? -0.2 : 0.2))); // TODO: edit based on colours (hue or smth)
- return c;
- }
-
- function on(c: color): color {
- if (c.hslLightness < 0.5)
- return Qt.hsla(c.hslHue, c.hslSaturation, 0.9, 1);
- return Qt.hsla(c.hslHue, c.hslSaturation, 0.1, 1);
- }
-
- function load(data: string, isPreview: bool): void {
- const colours = isPreview ? preview : current;
- const scheme = JSON.parse(data);
-
- light = scheme.mode === "light";
-
- for (const [name, colour] of Object.entries(scheme.colours)) {
- const propName = colourNames.includes(name) ? name : `m3${name}`;
- if (colours.hasOwnProperty(propName))
- colours[propName] = `#${colour}`;
- }
-
- if (!isPreview || (isPreview && endPreviewOnNextChange)) {
- showPreview = false;
- endPreviewOnNextChange = false;
- }
- }
-
- function setMode(mode: string): void {
- Quickshell.execDetached(["caelestia", "scheme", "set", "--notify", "-m", mode]);
- }
-
- FileView {
- path: `${Paths.state}/scheme.json`
- watchChanges: true
- onFileChanged: reload()
- onLoaded: root.load(text(), false)
- }
-
- component Transparency: QtObject {
- readonly property bool enabled: false
- readonly property real base: 0.78
- readonly property real layers: 0.58
- }
-
- component Colours: QtObject {
- property color m3primary_paletteKeyColor: "#7870AB"
- property color m3secondary_paletteKeyColor: "#78748A"
- property color m3tertiary_paletteKeyColor: "#976A7D"
- property color m3neutral_paletteKeyColor: "#79767D"
- property color m3neutral_variant_paletteKeyColor: "#797680"
- property color m3background: "#141318"
- property color m3onBackground: "#E5E1E9"
- property color m3surface: "#141318"
- property color m3surfaceDim: "#141318"
- property color m3surfaceBright: "#3A383E"
- property color m3surfaceContainerLowest: "#0E0D13"
- property color m3surfaceContainerLow: "#1C1B20"
- property color m3surfaceContainer: "#201F25"
- property color m3surfaceContainerHigh: "#2B292F"
- property color m3surfaceContainerHighest: "#35343A"
- property color m3onSurface: "#E5E1E9"
- property color m3surfaceVariant: "#48454E"
- property color m3onSurfaceVariant: "#C9C5D0"
- property color m3inverseSurface: "#E5E1E9"
- property color m3inverseOnSurface: "#312F36"
- property color m3outline: "#938F99"
- property color m3outlineVariant: "#48454E"
- property color m3shadow: "#000000"
- property color m3scrim: "#000000"
- property color m3surfaceTint: "#C8BFFF"
- property color m3primary: "#C8BFFF"
- property color m3onPrimary: "#30285F"
- property color m3primaryContainer: "#473F77"
- property color m3onPrimaryContainer: "#E5DEFF"
- property color m3inversePrimary: "#5F5791"
- property color m3secondary: "#C9C3DC"
- property color m3onSecondary: "#312E41"
- property color m3secondaryContainer: "#484459"
- property color m3onSecondaryContainer: "#E5DFF9"
- property color m3tertiary: "#ECB8CD"
- property color m3onTertiary: "#482536"
- property color m3tertiaryContainer: "#B38397"
- property color m3onTertiaryContainer: "#000000"
- property color m3error: "#EA8DC1"
- property color m3onError: "#690005"
- property color m3errorContainer: "#93000A"
- property color m3onErrorContainer: "#FFDAD6"
- property color m3primaryFixed: "#E5DEFF"
- property color m3primaryFixedDim: "#C8BFFF"
- property color m3onPrimaryFixed: "#1B1149"
- property color m3onPrimaryFixedVariant: "#473F77"
- property color m3secondaryFixed: "#E5DFF9"
- property color m3secondaryFixedDim: "#C9C3DC"
- property color m3onSecondaryFixed: "#1C192B"
- property color m3onSecondaryFixedVariant: "#484459"
- property color m3tertiaryFixed: "#FFD8E7"
- property color m3tertiaryFixedDim: "#ECB8CD"
- property color m3onTertiaryFixed: "#301121"
- property color m3onTertiaryFixedVariant: "#613B4C"
-
- property color rosewater: "#B8C4FF"
- property color flamingo: "#DBB9F8"
- property color pink: "#F3B3E3"
- property color mauve: "#D0BDFE"
- property color red: "#F8B3D1"
- property color maroon: "#F6B2DA"
- property color peach: "#E4B7F4"
- property color yellow: "#C3C0FF"
- property color green: "#ADC6FF"
- property color teal: "#D4BBFC"
- property color sky: "#CBBEFF"
- property color sapphire: "#BDC2FF"
- property color blue: "#C7BFFF"
- property color lavender: "#EAB5ED"
- }
-}
diff --git a/dots/quickshell/services/Hyprland.qml b/dots/quickshell/services/Hyprland.qml
deleted file mode 100644
index b8fa7c5..0000000
--- a/dots/quickshell/services/Hyprland.qml
+++ /dev/null
@@ -1,113 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-import Quickshell.Hyprland
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property list clients: []
- readonly property var workspaces: Hyprland.workspaces
- readonly property var monitors: Hyprland.monitors
- property Client activeClient: null
- readonly property HyprlandWorkspace activeWorkspace: focusedMonitor?.activeWorkspace ?? null
- readonly property HyprlandMonitor focusedMonitor: Hyprland.focusedMonitor
- readonly property int activeWsId: activeWorkspace?.id ?? 1
- property point cursorPos
-
- function reload() {
- Hyprland.refreshWorkspaces();
- Hyprland.refreshMonitors();
- getClients.running = true;
- getActiveClient.running = true;
- }
-
- function dispatch(request: string): void {
- Hyprland.dispatch(request);
- }
-
- Component.onCompleted: reload()
-
- Connections {
- target: Hyprland
-
- function onRawEvent(event: HyprlandEvent): void {
- if (!event.name.endsWith("v2"))
- root.reload();
- }
- }
-
- Process {
- id: getClients
- command: ["hyprctl", "-j", "clients"]
- stdout: StdioCollector {
- onStreamFinished: {
- const clients = JSON.parse(text);
- const rClients = root.clients;
-
- const destroyed = rClients.filter(rc => !clients.find(c => c.address === rc.address));
- for (const client of destroyed)
- rClients.splice(rClients.indexOf(client), 1).forEach(c => c.destroy());
-
- for (const client of clients) {
- const match = rClients.find(c => c.address === client.address);
- if (match) {
- match.lastIpcObject = client;
- } else {
- rClients.push(clientComp.createObject(root, {
- lastIpcObject: client
- }));
- }
- }
- }
- }
- }
-
- Process {
- id: getActiveClient
- command: ["hyprctl", "-j", "activewindow"]
- stdout: StdioCollector {
- onStreamFinished: {
- const client = JSON.parse(text);
- const rClient = root.activeClient;
- if (client.address) {
- if (rClient)
- rClient.lastIpcObject = client;
- else
- root.activeClient = clientComp.createObject(root, {
- lastIpcObject: client
- });
- } else if (rClient) {
- rClient.destroy();
- root.activeClient = null;
- }
- }
- }
- }
-
- component Client: QtObject {
- required property var lastIpcObject
- readonly property string address: lastIpcObject.address
- readonly property string wmClass: lastIpcObject.class
- readonly property string title: lastIpcObject.title
- readonly property string initialClass: lastIpcObject.initialClass
- readonly property string initialTitle: lastIpcObject.initialTitle
- readonly property int x: lastIpcObject.at[0]
- readonly property int y: lastIpcObject.at[1]
- readonly property int width: lastIpcObject.size[0]
- readonly property int height: lastIpcObject.size[1]
- readonly property HyprlandWorkspace workspace: Hyprland.workspaces.values.find(w => w.id === lastIpcObject.workspace.id) ?? null
- readonly property bool floating: lastIpcObject.floating
- readonly property bool fullscreen: lastIpcObject.fullscreen
- readonly property int pid: lastIpcObject.pid
- readonly property int focusHistoryId: lastIpcObject.focusHistoryID
- }
-
- Component {
- id: clientComp
-
- Client {}
- }
-}
diff --git a/dots/quickshell/services/Network.qml b/dots/quickshell/services/Network.qml
deleted file mode 100644
index 6a7f50e..0000000
--- a/dots/quickshell/services/Network.qml
+++ /dev/null
@@ -1,77 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property list networks: []
- readonly property AccessPoint active: networks.find(n => n.active) ?? null
-
- reloadableId: "network"
-
- Process {
- running: true
- command: ["nmcli", "m"]
- stdout: SplitParser {
- onRead: getNetworks.running = true
- }
- }
-
- Process {
- id: getNetworks
- running: true
- command: ["nmcli", "-g", "ACTIVE,SIGNAL,FREQ,SSID,BSSID", "d", "w"]
- stdout: StdioCollector {
- onStreamFinished: {
- const PLACEHOLDER = "STRINGWHICHHOPEFULLYWONTBEUSED";
- const rep = new RegExp("\\\\:", "g");
- const rep2 = new RegExp(PLACEHOLDER, "g");
-
- const networks = text.trim().split("\n").map(n => {
- const net = n.replace(rep, PLACEHOLDER).split(":");
- return {
- active: net[0] === "yes",
- strength: parseInt(net[1]),
- frequency: parseInt(net[2]),
- ssid: net[3],
- bssid: net[4].replace(rep2, ":")
- };
- });
- const rNetworks = root.networks;
-
- const destroyed = rNetworks.filter(rn => !networks.find(n => n.frequency === rn.frequency && n.ssid === rn.ssid && n.bssid === rn.bssid));
- for (const network of destroyed)
- rNetworks.splice(rNetworks.indexOf(network), 1).forEach(n => n.destroy());
-
- for (const network of networks) {
- const match = rNetworks.find(n => n.frequency === network.frequency && n.ssid === network.ssid && n.bssid === network.bssid);
- if (match) {
- match.lastIpcObject = network;
- } else {
- rNetworks.push(apComp.createObject(root, {
- lastIpcObject: network
- }));
- }
- }
- }
- }
- }
-
- component AccessPoint: QtObject {
- required property var lastIpcObject
- readonly property string ssid: lastIpcObject.ssid
- readonly property string bssid: lastIpcObject.bssid
- readonly property int strength: lastIpcObject.strength
- readonly property int frequency: lastIpcObject.frequency
- readonly property bool active: lastIpcObject.active
- }
-
- Component {
- id: apComp
-
- AccessPoint {}
- }
-}
diff --git a/dots/quickshell/services/Notifs.qml b/dots/quickshell/services/Notifs.qml
deleted file mode 100644
index 73d98a2..0000000
--- a/dots/quickshell/services/Notifs.qml
+++ /dev/null
@@ -1,108 +0,0 @@
-pragma Singleton
-pragma ComponentBehavior: Bound
-
-import "root:/widgets"
-import "root:/config"
-import Quickshell
-import Quickshell.Io
-import Quickshell.Services.Notifications
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property list list: []
- readonly property list popups: list.filter(n => n.popup)
-
- NotificationServer {
- id: server
-
- keepOnReload: false
- actionsSupported: true
- bodyHyperlinksSupported: true
- bodyImagesSupported: true
- bodyMarkupSupported: true
- imageSupported: true
-
- onNotification: notif => {
- notif.tracked = true;
-
- root.list.push(notifComp.createObject(root, {
- popup: true,
- notification: notif
- }));
- }
- }
-
- CustomShortcut {
- name: "clearNotifs"
- description: "Clear all notifications"
- onPressed: {
- for (const notif of root.list)
- notif.popup = false;
- }
- }
-
- IpcHandler {
- target: "notifs"
-
- function clear(): void {
- for (const notif of root.list)
- notif.popup = false;
- }
- }
-
- component Notif: QtObject {
- id: notif
-
- property bool popup
- readonly property date time: new Date()
- readonly property string timeStr: {
- const diff = Time.date.getTime() - time.getTime();
- const m = Math.floor(diff / 60000);
- const h = Math.floor(m / 60);
-
- if (h < 1 && m < 1)
- return "now";
- if (h < 1)
- return `${m}m`;
- return `${h}h`;
- }
-
- required property Notification notification
- readonly property string summary: notification.summary
- readonly property string body: notification.body
- readonly property string appIcon: notification.appIcon
- readonly property string appName: notification.appName
- readonly property string image: notification.image
- readonly property var urgency: notification.urgency // Idk why NotificationUrgency doesn't work
- readonly property list actions: notification.actions
-
- readonly property Timer timer: Timer {
- running: true
- interval: notif.notification.expireTimeout > 0 ? notif.notification.expireTimeout : Config.notifs.defaultExpireTimeout
- onTriggered: {
- if (Config.notifs.expire)
- notif.popup = false;
- }
- }
-
- readonly property Connections conn: Connections {
- target: notif.notification.Retainable
-
- function onDropped(): void {
- root.list.splice(root.list.indexOf(notif), 1);
- }
-
- function onAboutToDestroy(): void {
- notif.destroy();
- }
- }
- }
-
- Component {
- id: notifComp
-
- Notif {}
- }
-}
diff --git a/dots/quickshell/services/Players.qml b/dots/quickshell/services/Players.qml
deleted file mode 100644
index e9a3de4..0000000
--- a/dots/quickshell/services/Players.qml
+++ /dev/null
@@ -1,97 +0,0 @@
-pragma Singleton
-
-import "root:/widgets"
-import Quickshell
-import Quickshell.Io
-import Quickshell.Services.Mpris
-
-Singleton {
- id: root
-
- readonly property list list: Mpris.players.values
- readonly property MprisPlayer active: manualActive ?? list.find(p => p.identity === "Spotify") ?? list[0] ?? null
- property MprisPlayer manualActive
-
- CustomShortcut {
- name: "mediaToggle"
- description: "Toggle media playback"
- onPressed: {
- const active = root.active;
- if (active && active.canTogglePlaying)
- active.togglePlaying();
- }
- }
-
- CustomShortcut {
- name: "mediaPrev"
- description: "Previous track"
- onPressed: {
- const active = root.active;
- if (active && active.canGoPrevious)
- active.previous();
- }
- }
-
- CustomShortcut {
- name: "mediaNext"
- description: "Next track"
- onPressed: {
- const active = root.active;
- if (active && active.canGoNext)
- active.next();
- }
- }
-
- CustomShortcut {
- name: "mediaStop"
- description: "Stop media playback"
- onPressed: root.active?.stop()
- }
-
- IpcHandler {
- target: "mpris"
-
- function getActive(prop: string): string {
- const active = root.active;
- return active ? active[prop] ?? "Invalid property" : "No active player";
- }
-
- function list(): string {
- return root.list.map(p => p.identity).join("\n");
- }
-
- function play(): void {
- const active = root.active;
- if (active?.canPlay)
- active.play();
- }
-
- function pause(): void {
- const active = root.active;
- if (active?.canPause)
- active.pause();
- }
-
- function playPause(): void {
- const active = root.active;
- if (active?.canTogglePlaying)
- active.togglePlaying();
- }
-
- function previous(): void {
- const active = root.active;
- if (active?.canGoPrevious)
- active.previous();
- }
-
- function next(): void {
- const active = root.active;
- if (active?.canGoNext)
- active.next();
- }
-
- function stop(): void {
- root.active?.stop();
- }
- }
-}
diff --git a/dots/quickshell/services/SystemUsage.qml b/dots/quickshell/services/SystemUsage.qml
deleted file mode 100644
index 9bf665a..0000000
--- a/dots/quickshell/services/SystemUsage.qml
+++ /dev/null
@@ -1,196 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- property real cpuPerc
- property real cpuTemp
- property real gpuPerc
- property real gpuTemp
- property int memUsed
- property int memTotal
- readonly property real memPerc: memTotal > 0 ? memUsed / memTotal : 0
- property int storageUsed
- property int storageTotal
- property real storagePerc: storageTotal > 0 ? storageUsed / storageTotal : 0
-
- property int lastCpuIdle
- property int lastCpuTotal
-
- function formatKib(kib: int): var {
- const mib = 1024;
- const gib = 1024 ** 2;
- const tib = 1024 ** 3;
-
- if (kib >= tib)
- return {
- value: kib / tib,
- unit: "TiB"
- };
- if (kib >= gib)
- return {
- value: kib / gib,
- unit: "GiB"
- };
- if (kib >= mib)
- return {
- value: kib / mib,
- unit: "MiB"
- };
- return {
- value: kib,
- unit: "KiB"
- };
- }
-
- Timer {
- running: true
- interval: 3000
- repeat: true
- onTriggered: {
- stat.reload();
- meminfo.reload();
- storage.running = true;
- cpuTemp.running = true;
- gpuUsage.running = true;
- gpuTemp.running = true;
- }
- }
-
- FileView {
- id: stat
-
- path: "/proc/stat"
- onLoaded: {
- const data = text().match(/^cpu\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/);
- if (data) {
- const stats = data.slice(1).map(n => parseInt(n, 10));
- const total = stats.reduce((a, b) => a + b, 0);
- const idle = stats[3];
-
- const totalDiff = total - root.lastCpuTotal;
- const idleDiff = idle - root.lastCpuIdle;
- root.cpuPerc = totalDiff > 0 ? (1 - idleDiff / totalDiff) : 0;
-
- root.lastCpuTotal = total;
- root.lastCpuIdle = idle;
- }
- }
- }
-
- FileView {
- id: meminfo
-
- path: "/proc/meminfo"
- onLoaded: {
- const data = text();
- root.memTotal = parseInt(data.match(/MemTotal: *(\d+)/)[1], 10) || 1;
- root.memUsed = (root.memTotal - parseInt(data.match(/MemAvailable: *(\d+)/)[1], 10)) || 0;
- }
- }
-
- Process {
- id: storage
-
- running: true
- command: ["sh", "-c", "df | grep '^/dev/' | awk '{print $1, $3, $4}'"]
- stdout: StdioCollector {
- onStreamFinished: {
- const deviceMap = new Map();
-
- for (const line of text.trim().split("\n")) {
- if (line.trim() === "")
- continue;
-
- const parts = line.trim().split(/\s+/);
- if (parts.length >= 3) {
- const device = parts[0];
- const used = parseInt(parts[1], 10) || 0;
- const avail = parseInt(parts[2], 10) || 0;
-
- // Only keep the entry with the largest total space for each device
- if (!deviceMap.has(device) || (used + avail) > (deviceMap.get(device).used + deviceMap.get(device).avail)) {
- deviceMap.set(device, {
- used: used,
- avail: avail
- });
- }
- }
- }
-
- let totalUsed = 0;
- let totalAvail = 0;
-
- for (const [device, stats] of deviceMap) {
- totalUsed += stats.used;
- totalAvail += stats.avail;
- }
-
- root.storageUsed = totalUsed;
- root.storageTotal = totalUsed + totalAvail;
- }
- }
- }
-
- Process {
- id: cpuTemp
-
- running: true
- command: ["sh", "-c", "cat /sys/class/thermal/thermal_zone*/temp"]
- stdout: StdioCollector {
- onStreamFinished: {
- const temps = text.trim().split(" ");
- const sum = temps.reduce((acc, d) => acc + parseInt(d, 10), 0);
- root.cpuTemp = sum / temps.length / 1000;
- }
- }
- }
-
- Process {
- id: gpuUsage
-
- running: true
- command: ["sh", "-c", "cat /sys/class/drm/card*/device/gpu_busy_percent"]
- stdout: StdioCollector {
- onStreamFinished: {
- const percs = text.trim().split("\n");
- const sum = percs.reduce((acc, d) => acc + parseInt(d, 10), 0);
- root.gpuPerc = sum / percs.length / 100;
- }
- }
- }
-
- Process {
- id: gpuTemp
-
- running: true
- command: ["sensors"]
- stdout: StdioCollector {
- onStreamFinished: {
- let eligible = false;
- let sum = 0;
- let count = 0;
-
- for (const line of text.trim().split("\n")) {
- if (line === "Adapter: PCI adapter")
- eligible = true;
- else if (line === "")
- eligible = false;
- else if (eligible) {
- const match = line.match(/^(temp[0-9]+|GPU core|edge)+:\s+\+([0-9]+\.[0-9]+)°C/);
- if (match) {
- sum += parseFloat(match[2]);
- count++;
- }
- }
- }
-
- root.gpuTemp = count > 0 ? sum / count : 0;
- }
- }
- }
-}
diff --git a/dots/quickshell/services/Time.qml b/dots/quickshell/services/Time.qml
deleted file mode 100644
index c4b3913..0000000
--- a/dots/quickshell/services/Time.qml
+++ /dev/null
@@ -1,20 +0,0 @@
-pragma Singleton
-
-import Quickshell
-
-Singleton {
- property alias enabled: clock.enabled
- readonly property date date: clock.date
- readonly property int hours: clock.hours
- readonly property int minutes: clock.minutes
- readonly property int seconds: clock.seconds
-
- function format(fmt: string): string {
- return Qt.formatDateTime(clock.date, fmt);
- }
-
- SystemClock {
- id: clock
- precision: SystemClock.Seconds
- }
-}
diff --git a/dots/quickshell/services/Visibilities.qml b/dots/quickshell/services/Visibilities.qml
deleted file mode 100644
index eb6ddfb..0000000
--- a/dots/quickshell/services/Visibilities.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-pragma Singleton
-
-import Quickshell
-
-Singleton {
- property var screens: ({})
- property var panels: ({})
-
- function getForActive(): PersistentProperties {
- return Object.entries(screens).find(s => s[0].slice(s[0].indexOf('"') + 1, s[0].lastIndexOf('"')) === Hyprland.focusedMonitor.name)[1];
- }
-}
diff --git a/dots/quickshell/services/Wallpapers.qml b/dots/quickshell/services/Wallpapers.qml
deleted file mode 100644
index a667017..0000000
--- a/dots/quickshell/services/Wallpapers.qml
+++ /dev/null
@@ -1,117 +0,0 @@
-pragma Singleton
-
-import "root:/utils/scripts/fuzzysort.js" as Fuzzy
-import "root:/utils"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- readonly property string currentNamePath: `${Paths.state}/wallpaper/path.txt`.slice(7)
- readonly property string path: `${Paths.pictures}/Wallpapers`.slice(7)
- readonly property list extensions: ["jpg", "jpeg", "png", "webp", "tif", "tiff"]
-
- readonly property list list: wallpapers.instances
- property bool showPreview: false
- readonly property string current: showPreview ? previewPath : actualCurrent
- property string previewPath
- property string actualCurrent
-
- readonly property list preppedWalls: list.map(w => ({
- name: Fuzzy.prepare(w.name),
- path: Fuzzy.prepare(w.path),
- wall: w
- }))
-
- function fuzzyQuery(search: string): var {
- return Fuzzy.go(search, preppedWalls, {
- all: true,
- keys: ["name", "path"],
- scoreFn: r => r[0].score * 0.9 + r[1].score * 0.1
- }).map(r => r.obj.wall);
- }
-
- function setWallpaper(path: string): void {
- actualCurrent = path;
- setWall.path = path;
- setWall.startDetached();
- }
-
- function preview(path: string): void {
- previewPath = path;
- showPreview = true;
- getPreviewColoursProc.running = true;
- }
-
- function stopPreview(): void {
- showPreview = false;
- Colours.endPreviewOnNextChange = true;
- }
-
- reloadableId: "wallpapers"
-
- IpcHandler {
- target: "wallpaper"
-
- function get(): string {
- return root.actualCurrent;
- }
-
- function set(path: string): void {
- root.setWallpaper(path);
- }
-
- function list(): string {
- return root.list.map(w => w.path).join("\n");
- }
- }
-
- FileView {
- path: root.currentNamePath
- watchChanges: true
- onFileChanged: reload()
- onLoaded: root.actualCurrent = text().trim()
- }
-
- Process {
- id: getPreviewColoursProc
-
- command: ["caelestia", "wallpaper", "-p", root.previewPath]
- stdout: StdioCollector {
- onStreamFinished: {
- Colours.load(text, true);
- Colours.showPreview = true;
- }
- }
- }
-
- Process {
- id: setWall
-
- property string path
-
- command: ["caelestia", "wallpaper", "-f", path]
- }
-
- Process {
- running: true
- command: ["find", root.path, "-type", "d", "-path", '*/.*', "-prune", "-o", "-not", "-name", '.*', "-type", "f", "-print"]
- stdout: StdioCollector {
- onStreamFinished: wallpapers.model = text.trim().split("\n").filter(w => root.extensions.includes(w.slice(w.lastIndexOf(".") + 1))).sort()
- }
- }
-
- Variants {
- id: wallpapers
-
- Wallpaper {}
- }
-
- component Wallpaper: QtObject {
- required property string modelData
- readonly property string path: modelData
- readonly property string name: path.slice(path.lastIndexOf("/") + 1, path.lastIndexOf("."))
- }
-}
diff --git a/dots/quickshell/services/Weather.qml b/dots/quickshell/services/Weather.qml
deleted file mode 100644
index 29858eb..0000000
--- a/dots/quickshell/services/Weather.qml
+++ /dev/null
@@ -1,49 +0,0 @@
-pragma Singleton
-
-import "root:/config"
-import "root:/utils"
-import Quickshell
-import Quickshell.Io
-import QtQuick
-
-Singleton {
- id: root
-
- property string loc
- property string icon
- property string description
- property real temperature
-
- function reload(): void {
- if (Config.dashboard.weatherLocation)
- loc = Config.dashboard.weatherLocation;
- else
- ipProc.running = true;
- }
-
- onLocChanged: wttrProc.running = true
- Component.onCompleted: reload()
-
- Process {
- id: ipProc
-
- command: ["curl", "ipinfo.io"]
- stdout: StdioCollector {
- onStreamFinished: root.loc = JSON.parse(text).loc
- }
- }
-
- Process {
- id: wttrProc
-
- command: ["curl", `https://wttr.in/${root.loc}?format=j1`]
- stdout: StdioCollector {
- onStreamFinished: {
- const json = JSON.parse(text).current_condition[0];
- root.icon = Icons.getWeatherIcon(json.weatherCode);
- root.description = json.weatherDesc[0].value;
- root.temperature = parseFloat(json.temp_C);
- }
- }
- }
-}
diff --git a/dots/quickshell/shell.qml b/dots/quickshell/shell.qml
deleted file mode 100644
index 2a58cb2..0000000
--- a/dots/quickshell/shell.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import "modules"
-import "modules/drawers"
-import "modules/background"
-import Quickshell
-
-ShellRoot {
- Background {}
- Drawers {}
-
- Shortcuts {}
-}
diff --git a/dots/quickshell/utils/Icons.qml b/dots/quickshell/utils/Icons.qml
deleted file mode 100644
index 41ecbfa..0000000
--- a/dots/quickshell/utils/Icons.qml
+++ /dev/null
@@ -1,222 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-
-Singleton {
- id: root
-
- readonly property var osIcons: ({
- almalinux: "",
- alpine: "",
- arch: "",
- archcraft: "",
- arcolinux: "",
- artix: "",
- centos: "",
- debian: "",
- devuan: "",
- elementary: "",
- endeavouros: "",
- fedora: "",
- freebsd: "",
- garuda: "",
- gentoo: "",
- hyperbola: "",
- kali: "",
- linuxmint: "",
- mageia: "",
- openmandriva: "",
- manjaro: "",
- neon: "",
- nixos: "",
- opensuse: "",
- suse: "",
- sles: "",
- sles_sap: "",
- "opensuse-tumbleweed": "",
- parrot: "",
- pop: "",
- raspbian: "",
- rhel: "",
- rocky: "",
- slackware: "",
- solus: "",
- steamos: "",
- tails: "",
- trisquel: "",
- ubuntu: "",
- vanilla: "",
- void: "",
- zorin: ""
- })
-
- readonly property var weatherIcons: ({
- "113": "clear_day",
- "116": "partly_cloudy_day",
- "119": "cloud",
- "122": "cloud",
- "143": "foggy",
- "176": "rainy",
- "179": "rainy",
- "182": "rainy",
- "185": "rainy",
- "200": "thunderstorm",
- "227": "cloudy_snowing",
- "230": "snowing_heavy",
- "248": "foggy",
- "260": "foggy",
- "263": "rainy",
- "266": "rainy",
- "281": "rainy",
- "284": "rainy",
- "293": "rainy",
- "296": "rainy",
- "299": "rainy",
- "302": "weather_hail",
- "305": "rainy",
- "308": "weather_hail",
- "311": "rainy",
- "314": "rainy",
- "317": "rainy",
- "320": "cloudy_snowing",
- "323": "cloudy_snowing",
- "326": "cloudy_snowing",
- "329": "snowing_heavy",
- "332": "snowing_heavy",
- "335": "snowing",
- "338": "snowing_heavy",
- "350": "rainy",
- "353": "rainy",
- "356": "rainy",
- "359": "weather_hail",
- "362": "rainy",
- "365": "rainy",
- "368": "cloudy_snowing",
- "371": "snowing",
- "374": "rainy",
- "377": "rainy",
- "386": "thunderstorm",
- "389": "thunderstorm",
- "392": "thunderstorm",
- "395": "snowing"
- })
-
- readonly property var desktopEntrySubs: ({})
-
- readonly property var categoryIcons: ({
- WebBrowser: "web",
- Printing: "print",
- Security: "security",
- Network: "chat",
- Archiving: "archive",
- Compression: "archive",
- Development: "code",
- IDE: "code",
- TextEditor: "edit_note",
- Audio: "music_note",
- Music: "music_note",
- Player: "music_note",
- Recorder: "mic",
- Game: "sports_esports",
- FileTools: "files",
- FileManager: "files",
- Filesystem: "files",
- FileTransfer: "files",
- Settings: "settings",
- DesktopSettings: "settings",
- HardwareSettings: "settings",
- TerminalEmulator: "terminal",
- ConsoleOnly: "terminal",
- Utility: "build",
- Monitor: "monitor_heart",
- Midi: "graphic_eq",
- Mixer: "graphic_eq",
- AudioVideoEditing: "video_settings",
- AudioVideo: "music_video",
- Video: "videocam",
- Building: "construction",
- Graphics: "photo_library",
- "2DGraphics": "photo_library",
- RasterGraphics: "photo_library",
- TV: "tv",
- System: "host",
- Office: "content_paste"
- })
-
- property string osIcon: ""
- property string osName
-
- function getDesktopEntry(name: string): DesktopEntry {
- name = name.toLowerCase().replace(/ /g, "-");
-
- if (desktopEntrySubs.hasOwnProperty(name))
- name = desktopEntrySubs[name];
-
- return DesktopEntries.applications.values.find(a => a.id.toLowerCase() === name) ?? null;
- }
-
- function getAppIcon(name: string, fallback: string): string {
- return Quickshell.iconPath(getDesktopEntry(name)?.icon, fallback);
- }
-
- function getAppCategoryIcon(name: string, fallback: string): string {
- const categories = getDesktopEntry(name)?.categories;
-
- if (categories)
- for (const [key, value] of Object.entries(categoryIcons))
- if (categories.includes(key))
- return value;
- return fallback;
- }
-
- function getNetworkIcon(strength: int): string {
- if (strength >= 80)
- return "signal_wifi_4_bar";
- if (strength >= 60)
- return "network_wifi_3_bar";
- if (strength >= 40)
- return "network_wifi_2_bar";
- if (strength >= 20)
- return "network_wifi_1_bar";
- return "signal_wifi_0_bar";
- }
-
- function getBluetoothIcon(icon: string): string {
- if (icon.includes("headset") || icon.includes("headphones"))
- return "headphones";
- if (icon.includes("audio"))
- return "speaker";
- if (icon.includes("phone"))
- return "smartphone";
- return "bluetooth";
- }
-
- function getWeatherIcon(code: string): string {
- if (weatherIcons.hasOwnProperty(code))
- return weatherIcons[code];
- return "air";
- }
-
- FileView {
- path: "/etc/os-release"
- onLoaded: {
- const lines = text().split("\n");
- let osId = lines.find(l => l.startsWith("ID="))?.split("=")[1];
- if (root.osIcons.hasOwnProperty(osId))
- root.osIcon = root.osIcons[osId];
- else {
- const osIdLike = lines.find(l => l.startsWith("ID_LIKE="))?.split("=")[1];
- if (osIdLike)
- for (const id of osIdLike.split(" "))
- if (root.osIcons.hasOwnProperty(id))
- return root.osIcon = root.osIcons[id];
- }
-
- let nameLine = lines.find(l => l.startsWith("PRETTY_NAME="));
- if (!nameLine)
- nameLine = lines.find(l => l.startsWith("NAME="));
- root.osName = nameLine.split("=")[1].slice(1, -1);
- }
- }
-}
diff --git a/dots/quickshell/utils/Paths.qml b/dots/quickshell/utils/Paths.qml
deleted file mode 100644
index bd57608..0000000
--- a/dots/quickshell/utils/Paths.qml
+++ /dev/null
@@ -1,32 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-import Qt.labs.platform
-
-Singleton {
- id: root
-
- readonly property url home: StandardPaths.standardLocations(StandardPaths.HomeLocation)[0]
- readonly property url pictures: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
-
- readonly property url data: `${StandardPaths.standardLocations(StandardPaths.GenericDataLocation)[0]}/caelestia`
- readonly property url state: `${StandardPaths.standardLocations(StandardPaths.GenericStateLocation)[0]}/caelestia`
- readonly property url cache: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/caelestia`
- readonly property url config: `${StandardPaths.standardLocations(StandardPaths.GenericConfigLocation)[0]}/caelestia`
-
- readonly property url imagecache: `${cache}/imagecache`
-
- function mkdir(path: url): void {
- mkdirProc.path = path.toString().replace("file://", "");
- mkdirProc.startDetached();
- }
-
- Process {
- id: mkdirProc
-
- property string path
-
- command: ["mkdir", "-p", path]
- }
-}
diff --git a/dots/quickshell/utils/scripts/fuzzysort.js b/dots/quickshell/utils/scripts/fuzzysort.js
deleted file mode 100644
index f308fc6..0000000
--- a/dots/quickshell/utils/scripts/fuzzysort.js
+++ /dev/null
@@ -1,679 +0,0 @@
-.pragma library
-
-var single = (search, target) => {
- if(!search || !target) return NULL
-
- var preparedSearch = getPreparedSearch(search)
- if(!isPrepared(target)) target = getPrepared(target)
-
- var searchBitflags = preparedSearch.bitflags
- if((searchBitflags & target._bitflags) !== searchBitflags) return NULL
-
- return algorithm(preparedSearch, target)
-}
-
-var go = (search, targets, options) => {
- if(!search) return options?.all ? all(targets, options) : noResults
-
- var preparedSearch = getPreparedSearch(search)
- var searchBitflags = preparedSearch.bitflags
- var containsSpace = preparedSearch.containsSpace
-
- var threshold = denormalizeScore( options?.threshold || 0 )
- var limit = options?.limit || INFINITY
-
- var resultsLen = 0; var limitedCount = 0
- var targetsLen = targets.length
-
- function push_result(result) {
- if(resultsLen < limit) { q.add(result); ++resultsLen }
- else {
- ++limitedCount
- if(result._score > q.peek()._score) q.replaceTop(result)
- }
- }
-
- // This code is copy/pasted 3 times for performance reasons [options.key, options.keys, no keys]
-
- // options.key
- if(options?.key) {
- var key = options.key
- for(var i = 0; i < targetsLen; ++i) { var obj = targets[i]
- var target = getValue(obj, key)
- if(!target) continue
- if(!isPrepared(target)) target = getPrepared(target)
-
- if((searchBitflags & target._bitflags) !== searchBitflags) continue
- var result = algorithm(preparedSearch, target)
- if(result === NULL) continue
- if(result._score < threshold) continue
-
- result.obj = obj
- push_result(result)
- }
-
- // options.keys
- } else if(options?.keys) {
- var keys = options.keys
- var keysLen = keys.length
-
- outer: for(var i = 0; i < targetsLen; ++i) { var obj = targets[i]
-
- { // early out based on bitflags
- var keysBitflags = 0
- for (var keyI = 0; keyI < keysLen; ++keyI) {
- var key = keys[keyI]
- var target = getValue(obj, key)
- if(!target) { tmpTargets[keyI] = noTarget; continue }
- if(!isPrepared(target)) target = getPrepared(target)
- tmpTargets[keyI] = target
-
- keysBitflags |= target._bitflags
- }
-
- if((searchBitflags & keysBitflags) !== searchBitflags) continue
- }
-
- if(containsSpace) for(let i=0; i -1000) {
- if(keysSpacesBestScores[i] > NEGATIVE_INFINITY) {
- var tmp = (keysSpacesBestScores[i] + allowPartialMatchScores[i]) / 4/*bonus score for having multiple matches*/
- if(tmp > keysSpacesBestScores[i]) keysSpacesBestScores[i] = tmp
- }
- }
- if(allowPartialMatchScores[i] > keysSpacesBestScores[i]) keysSpacesBestScores[i] = allowPartialMatchScores[i]
- }
- }
-
- if(containsSpace) {
- for(let i=0; i -1000) {
- if(score > NEGATIVE_INFINITY) {
- var tmp = (score + result._score) / 4/*bonus score for having multiple matches*/
- if(tmp > score) score = tmp
- }
- }
- if(result._score > score) score = result._score
- }
- }
-
- objResults.obj = obj
- objResults._score = score
- if(options?.scoreFn) {
- score = options.scoreFn(objResults)
- if(!score) continue
- score = denormalizeScore(score)
- objResults._score = score
- }
-
- if(score < threshold) continue
- push_result(objResults)
- }
-
- // no keys
- } else {
- for(var i = 0; i < targetsLen; ++i) { var target = targets[i]
- if(!target) continue
- if(!isPrepared(target)) target = getPrepared(target)
-
- if((searchBitflags & target._bitflags) !== searchBitflags) continue
- var result = algorithm(preparedSearch, target)
- if(result === NULL) continue
- if(result._score < threshold) continue
-
- push_result(result)
- }
- }
-
- if(resultsLen === 0) return noResults
- var results = new Array(resultsLen)
- for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
- results.total = resultsLen + limitedCount
- return results
-}
-
-
-// this is written as 1 function instead of 2 for minification. perf seems fine ...
-// except when minified. the perf is very slow
-var highlight = (result, open='', close=' ') => {
- var callback = typeof open === 'function' ? open : undefined
-
- var target = result.target
- var targetLen = target.length
- var indexes = result.indexes
- var highlighted = ''
- var matchI = 0
- var indexesI = 0
- var opened = false
- var parts = []
-
- for(var i = 0; i < targetLen; ++i) { var char = target[i]
- if(indexes[indexesI] === i) {
- ++indexesI
- if(!opened) { opened = true
- if(callback) {
- parts.push(highlighted); highlighted = ''
- } else {
- highlighted += open
- }
- }
-
- if(indexesI === indexes.length) {
- if(callback) {
- highlighted += char
- parts.push(callback(highlighted, matchI++)); highlighted = ''
- parts.push(target.substr(i+1))
- } else {
- highlighted += char + close + target.substr(i+1)
- }
- break
- }
- } else {
- if(opened) { opened = false
- if(callback) {
- parts.push(callback(highlighted, matchI++)); highlighted = ''
- } else {
- highlighted += close
- }
- }
- }
- highlighted += char
- }
-
- return callback ? parts : highlighted
-}
-
-
-var prepare = (target) => {
- if(typeof target === 'number') target = ''+target
- else if(typeof target !== 'string') target = ''
- var info = prepareLowerInfo(target)
- return new_result(target, {_targetLower:info._lower, _targetLowerCodes:info.lowerCodes, _bitflags:info.bitflags})
-}
-
-var cleanup = () => { preparedCache.clear(); preparedSearchCache.clear() }
-
-
-// Below this point is only internal code
-// Below this point is only internal code
-// Below this point is only internal code
-// Below this point is only internal code
-
-
-class Result {
- get ['indexes']() { return this._indexes.slice(0, this._indexes.len).sort((a,b)=>a-b) }
- set ['indexes'](indexes) { return this._indexes = indexes }
- ['highlight'](open, close) { return highlight(this, open, close) }
- get ['score']() { return normalizeScore(this._score) }
- set ['score'](score) { this._score = denormalizeScore(score) }
-}
-
-class KeysResult extends Array {
- get ['score']() { return normalizeScore(this._score) }
- set ['score'](score) { this._score = denormalizeScore(score) }
-}
-
-var new_result = (target, options) => {
- const result = new Result()
- result['target'] = target
- result['obj'] = options.obj ?? NULL
- result._score = options._score ?? NEGATIVE_INFINITY
- result._indexes = options._indexes ?? []
- result._targetLower = options._targetLower ?? ''
- result._targetLowerCodes = options._targetLowerCodes ?? NULL
- result._nextBeginningIndexes = options._nextBeginningIndexes ?? NULL
- result._bitflags = options._bitflags ?? 0
- return result
-}
-
-
-var normalizeScore = score => {
- if(score === NEGATIVE_INFINITY) return 0
- if(score > 1) return score
- return Math.E ** ( ((-score + 1)**.04307 - 1) * -2)
-}
-var denormalizeScore = normalizedScore => {
- if(normalizedScore === 0) return NEGATIVE_INFINITY
- if(normalizedScore > 1) return normalizedScore
- return 1 - Math.pow((Math.log(normalizedScore) / -2 + 1), 1 / 0.04307)
-}
-
-
-var prepareSearch = (search) => {
- if(typeof search === 'number') search = ''+search
- else if(typeof search !== 'string') search = ''
- search = search.trim()
- var info = prepareLowerInfo(search)
-
- var spaceSearches = []
- if(info.containsSpace) {
- var searches = search.split(/\s+/)
- searches = [...new Set(searches)] // distinct
- for(var i=0; i {
- if(target.length > 999) return prepare(target) // don't cache huge targets
- var targetPrepared = preparedCache.get(target)
- if(targetPrepared !== undefined) return targetPrepared
- targetPrepared = prepare(target)
- preparedCache.set(target, targetPrepared)
- return targetPrepared
-}
-var getPreparedSearch = (search) => {
- if(search.length > 999) return prepareSearch(search) // don't cache huge searches
- var searchPrepared = preparedSearchCache.get(search)
- if(searchPrepared !== undefined) return searchPrepared
- searchPrepared = prepareSearch(search)
- preparedSearchCache.set(search, searchPrepared)
- return searchPrepared
-}
-
-
-var all = (targets, options) => {
- var results = []; results.total = targets.length // this total can be wrong if some targets are skipped
-
- var limit = options?.limit || INFINITY
-
- if(options?.key) {
- for(var i=0;i= limit) return results
- }
- } else if(options?.keys) {
- for(var i=0;i= 0; --keyI) {
- var target = getValue(obj, options.keys[keyI])
- if(!target) { objResults[keyI] = noTarget; continue }
- if(!isPrepared(target)) target = getPrepared(target)
- target._score = NEGATIVE_INFINITY
- target._indexes.len = 0
- objResults[keyI] = target
- }
- objResults.obj = obj
- objResults._score = NEGATIVE_INFINITY
- results.push(objResults); if(results.length >= limit) return results
- }
- } else {
- for(var i=0;i= limit) return results
- }
- }
-
- return results
-}
-
-
-var algorithm = (preparedSearch, prepared, allowSpaces=false, allowPartialMatch=false) => {
- if(allowSpaces===false && preparedSearch.containsSpace) return algorithmSpaces(preparedSearch, prepared, allowPartialMatch)
-
- var searchLower = preparedSearch._lower
- var searchLowerCodes = preparedSearch.lowerCodes
- var searchLowerCode = searchLowerCodes[0]
- var targetLowerCodes = prepared._targetLowerCodes
- var searchLen = searchLowerCodes.length
- var targetLen = targetLowerCodes.length
- var searchI = 0 // where we at
- var targetI = 0 // where you at
- var matchesSimpleLen = 0
-
- // very basic fuzzy match; to remove non-matching targets ASAP!
- // walk through target. find sequential matches.
- // if all chars aren't found then exit
- for(;;) {
- var isMatch = searchLowerCode === targetLowerCodes[targetI]
- if(isMatch) {
- matchesSimple[matchesSimpleLen++] = targetI
- ++searchI; if(searchI === searchLen) break
- searchLowerCode = searchLowerCodes[searchI]
- }
- ++targetI; if(targetI >= targetLen) return NULL // Failed to find searchI
- }
-
- var searchI = 0
- var successStrict = false
- var matchesStrictLen = 0
-
- var nextBeginningIndexes = prepared._nextBeginningIndexes
- if(nextBeginningIndexes === NULL) nextBeginningIndexes = prepared._nextBeginningIndexes = prepareNextBeginningIndexes(prepared.target)
- targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
-
- // Our target string successfully matched all characters in sequence!
- // Let's try a more advanced and strict test to improve the score
- // only count it as a match if it's consecutive or a beginning character!
- var backtrackCount = 0
- if(targetI !== targetLen) for(;;) {
- if(targetI >= targetLen) {
- // We failed to find a good spot for this search char, go back to the previous search char and force it forward
- if(searchI <= 0) break // We failed to push chars forward for a better match
-
- ++backtrackCount; if(backtrackCount > 200) break // exponential backtracking is taking too long, just give up and return a bad match
-
- --searchI
- var lastMatch = matchesStrict[--matchesStrictLen]
- targetI = nextBeginningIndexes[lastMatch]
-
- } else {
- var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI]
- if(isMatch) {
- matchesStrict[matchesStrictLen++] = targetI
- ++searchI; if(searchI === searchLen) { successStrict = true; break }
- ++targetI
- } else {
- targetI = nextBeginningIndexes[targetI]
- }
- }
- }
-
- // check if it's a substring match
- var substringIndex = searchLen <= 1 ? -1 : prepared._targetLower.indexOf(searchLower, matchesSimple[0]) // perf: this is slow
- var isSubstring = !!~substringIndex
- var isSubstringBeginning = !isSubstring ? false : substringIndex===0 || prepared._nextBeginningIndexes[substringIndex-1] === substringIndex
-
- // if it's a substring match but not at a beginning index, let's try to find a substring starting at a beginning index for a better score
- if(isSubstring && !isSubstringBeginning) {
- for(var i=0; i {
- var score = 0
-
- var extraMatchGroupCount = 0
- for(var i = 1; i < searchLen; ++i) {
- if(matches[i] - matches[i-1] !== 1) {score -= matches[i]; ++extraMatchGroupCount}
- }
- var unmatchedDistance = matches[searchLen-1] - matches[0] - (searchLen-1)
-
- score -= (12+unmatchedDistance) * extraMatchGroupCount // penality for more groups
-
- if(matches[0] !== 0) score -= matches[0]*matches[0]*.2 // penality for not starting near the beginning
-
- if(!successStrict) {
- score *= 1000
- } else {
- // successStrict on a target with too many beginning indexes loses points for being a bad target
- var uniqueBeginningIndexes = 1
- for(var i = nextBeginningIndexes[0]; i < targetLen; i=nextBeginningIndexes[i]) ++uniqueBeginningIndexes
-
- if(uniqueBeginningIndexes > 24) score *= (uniqueBeginningIndexes-24)*10 // quite arbitrary numbers here ...
- }
-
- score -= (targetLen - searchLen)/2 // penality for longer targets
-
- if(isSubstring) score /= 1+searchLen*searchLen*1 // bonus for being a full substring
- if(isSubstringBeginning) score /= 1+searchLen*searchLen*1 // bonus for substring starting on a beginningIndex
-
- score -= (targetLen - searchLen)/2 // penality for longer targets
-
- return score
- }
-
- if(!successStrict) {
- if(isSubstring) for(var i=0; i {
- var seen_indexes = new Set()
- var score = 0
- var result = NULL
-
- var first_seen_index_last_search = 0
- var searches = preparedSearch.spaceSearches
- var searchesLen = searches.length
- var changeslen = 0
-
- // Return _nextBeginningIndexes back to its normal state
- var resetNextBeginningIndexes = () => {
- for(let i=changeslen-1; i>=0; i--) target._nextBeginningIndexes[nextBeginningIndexesChanges[i*2 + 0]] = nextBeginningIndexesChanges[i*2 + 1]
- }
-
- var hasAtLeast1Match = false
- for(var i=0; i=0; i--) {
- if(toReplace !== target._nextBeginningIndexes[i]) break
- target._nextBeginningIndexes[i] = newBeginningIndex
- nextBeginningIndexesChanges[changeslen*2 + 0] = i
- nextBeginningIndexesChanges[changeslen*2 + 1] = toReplace
- changeslen++
- }
- }
- }
-
- score += result._score / searchesLen
- allowPartialMatchScores[i] = result._score / searchesLen
-
- // dock points based on order otherwise "c man" returns Manifest.cpp instead of CheatManager.h
- if(result._indexes[0] < first_seen_index_last_search) {
- score -= (first_seen_index_last_search - result._indexes[0]) * 2
- }
- first_seen_index_last_search = result._indexes[0]
-
- for(var j=0; j score) {
- if(allowPartialMatch) {
- for(var i=0; i str.replace(/\p{Script=Latin}+/gu, match => match.normalize('NFD')).replace(/[\u0300-\u036f]/g, '')
-
-var prepareLowerInfo = (str) => {
- str = remove_accents(str)
- var strLen = str.length
- var lower = str.toLowerCase()
- var lowerCodes = [] // new Array(strLen) sparse array is too slow
- var bitflags = 0
- var containsSpace = false // space isn't stored in bitflags because of how searching with a space works
-
- for(var i = 0; i < strLen; ++i) {
- var lowerCode = lowerCodes[i] = lower.charCodeAt(i)
-
- if(lowerCode === 32) {
- containsSpace = true
- continue // it's important that we don't set any bitflags for space
- }
-
- var bit = lowerCode>=97&&lowerCode<=122 ? lowerCode-97 // alphabet
- : lowerCode>=48&&lowerCode<=57 ? 26 // numbers
- // 3 bits available
- : lowerCode<=127 ? 30 // other ascii
- : 31 // other utf8
- bitflags |= 1< {
- var targetLen = target.length
- var beginningIndexes = []; var beginningIndexesLen = 0
- var wasUpper = false
- var wasAlphanum = false
- for(var i = 0; i < targetLen; ++i) {
- var targetCode = target.charCodeAt(i)
- var isUpper = targetCode>=65&&targetCode<=90
- var isAlphanum = isUpper || targetCode>=97&&targetCode<=122 || targetCode>=48&&targetCode<=57
- var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum
- wasUpper = isUpper
- wasAlphanum = isAlphanum
- if(isBeginning) beginningIndexes[beginningIndexesLen++] = i
- }
- return beginningIndexes
-}
-var prepareNextBeginningIndexes = (target) => {
- target = remove_accents(target)
- var targetLen = target.length
- var beginningIndexes = prepareBeginningIndexes(target)
- var nextBeginningIndexes = [] // new Array(targetLen) sparse array is too slow
- var lastIsBeginning = beginningIndexes[0]
- var lastIsBeginningI = 0
- for(var i = 0; i < targetLen; ++i) {
- if(lastIsBeginning > i) {
- nextBeginningIndexes[i] = lastIsBeginning
- } else {
- lastIsBeginning = beginningIndexes[++lastIsBeginningI]
- nextBeginningIndexes[i] = lastIsBeginning===undefined ? targetLen : lastIsBeginning
- }
- }
- return nextBeginningIndexes
-}
-
-var preparedCache = new Map()
-var preparedSearchCache = new Map()
-
-// the theory behind these being globals is to reduce garbage collection by not making new arrays
-var matchesSimple = []; var matchesStrict = []
-var nextBeginningIndexesChanges = [] // allows straw berry to match strawberry well, by modifying the end of a substring to be considered a beginning index for the rest of the search
-var keysSpacesBestScores = []; var allowPartialMatchScores = []
-var tmpTargets = []; var tmpResults = []
-
-// prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop]
-// prop = 'key1.key2' 10ms
-// prop = ['key1', 'key2'] 27ms
-// prop = obj => obj.tags.join() ??ms
-var getValue = (obj, prop) => {
- var tmp = obj[prop]; if(tmp !== undefined) return tmp
- if(typeof prop === 'function') return prop(obj) // this should run first. but that makes string props slower
- var segs = prop
- if(!Array.isArray(prop)) segs = prop.split('.')
- var len = segs.length
- var i = -1
- while (obj && (++i < len)) obj = obj[segs[i]]
- return obj
-}
-
-var isPrepared = (x) => { return typeof x === 'object' && typeof x._bitflags === 'number' }
-var INFINITY = Infinity; var NEGATIVE_INFINITY = -INFINITY
-var noResults = []; noResults.total = 0
-var NULL = null
-
-var noTarget = prepare('')
-
-// Hacked version of https://github.com/lemire/FastPriorityQueue.js
-var fastpriorityqueue=r=>{var e=[],o=0,a={},v=r=>{for(var a=0,v=e[a],c=1;c>1]=e[a],c=1+(a<<1)}for(var f=a-1>>1;a>0&&v._score>1)e[a]=e[f];e[a]=v};return a.add=(r=>{var a=o;e[o++]=r;for(var v=a-1>>1;a>0&&r._score>1)e[a]=e[v];e[a]=r}),a.poll=(r=>{if(0!==o){var a=e[0];return e[0]=e[--o],v(),a}}),a.peek=(r=>{if(0!==o)return e[0]}),a.replaceTop=(r=>{e[0]=r,v()}),a}
-var q = fastpriorityqueue() // reuse this
-
diff --git a/dots/quickshell/widgets/CachingImage.qml b/dots/quickshell/widgets/CachingImage.qml
deleted file mode 100644
index 8f7f711..0000000
--- a/dots/quickshell/widgets/CachingImage.qml
+++ /dev/null
@@ -1,50 +0,0 @@
-import "root:/services"
-import "root:/utils"
-import Quickshell.Io
-import QtQuick
-
-Image {
- id: root
-
- property string path
- property string hash
- readonly property string cachePath: `${Paths.imagecache}/${hash}@${width}x${height}.png`.slice(7)
-
- asynchronous: true
- cache: false
- fillMode: Image.PreserveAspectCrop
- sourceSize.width: width
- sourceSize.height: height
-
- onPathChanged: {
- shaProc.signal(9);
- shaProc.path = path.replace("file://", "");
- shaProc.running = true;
- }
-
- onCachePathChanged: {
- if (hash)
- source = cachePath;
- }
-
- onStatusChanged: {
- if (source == cachePath && status === Image.Error)
- source = path;
- else if (source == path && status === Image.Ready) {
- Paths.mkdir(Paths.imagecache);
- const grabPath = cachePath;
- grabToImage(res => res.saveToFile(grabPath));
- }
- }
-
- Process {
- id: shaProc
-
- property string path
-
- command: ["sha256sum", path]
- stdout: StdioCollector {
- onStreamFinished: root.hash = text.split(" ")[0]
- }
- }
-}
diff --git a/dots/quickshell/widgets/Colouriser.qml b/dots/quickshell/widgets/Colouriser.qml
deleted file mode 100644
index 3c06f5a..0000000
--- a/dots/quickshell/widgets/Colouriser.qml
+++ /dev/null
@@ -1,15 +0,0 @@
-import "root:/config"
-import QtQuick
-import QtQuick.Effects
-
-MultiEffect {
- colorization: 1
-
- Behavior on colorizationColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/widgets/CustomShortcut.qml b/dots/quickshell/widgets/CustomShortcut.qml
deleted file mode 100644
index aa35ed8..0000000
--- a/dots/quickshell/widgets/CustomShortcut.qml
+++ /dev/null
@@ -1,5 +0,0 @@
-import Quickshell.Hyprland
-
-GlobalShortcut {
- appid: "caelestia"
-}
diff --git a/dots/quickshell/widgets/MaterialIcon.qml b/dots/quickshell/widgets/MaterialIcon.qml
deleted file mode 100644
index c86e5ce..0000000
--- a/dots/quickshell/widgets/MaterialIcon.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import "root:/config"
-
-StyledText {
- property real fill
-
- font.family: Appearance.font.family.material
- font.pointSize: Appearance.font.size.larger
- font.variableAxes: ({
- FILL: fill.toFixed(1)
- })
-}
diff --git a/dots/quickshell/widgets/StateLayer.qml b/dots/quickshell/widgets/StateLayer.qml
deleted file mode 100644
index 1c8f947..0000000
--- a/dots/quickshell/widgets/StateLayer.qml
+++ /dev/null
@@ -1,43 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-StyledRect {
- id: root
-
- readonly property alias hovered: mouse.hovered
- readonly property alias pressed: mouse.pressed
- property bool disabled
-
- function onClicked(event: MouseEvent): void {
- }
-
- anchors.fill: parent
-
- color: Colours.palette.m3onSurface
- opacity: disabled ? 0 : mouse.pressed ? 0.1 : mouse.hovered ? 0.08 : 0
-
- MouseArea {
- id: mouse
-
- property bool hovered
-
- anchors.fill: parent
- cursorShape: root.disabled ? undefined : Qt.PointingHandCursor
- hoverEnabled: true
-
- onEntered: hovered = true
- onExited: hovered = false
-
- onClicked: event => !root.disabled && root.onClicked(event)
- }
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.small
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/widgets/StyledClippingRect.qml b/dots/quickshell/widgets/StyledClippingRect.qml
deleted file mode 100644
index 477ce86..0000000
--- a/dots/quickshell/widgets/StyledClippingRect.qml
+++ /dev/null
@@ -1,17 +0,0 @@
-import "root:/config"
-import Quickshell.Widgets
-import QtQuick
-
-ClippingRectangle {
- id: root
-
- color: "transparent"
-
- Behavior on color {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/widgets/StyledRect.qml b/dots/quickshell/widgets/StyledRect.qml
deleted file mode 100644
index 108e5e0..0000000
--- a/dots/quickshell/widgets/StyledRect.qml
+++ /dev/null
@@ -1,16 +0,0 @@
-import "root:/config"
-import QtQuick
-
-Rectangle {
- id: root
-
- color: "transparent"
-
- Behavior on color {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/widgets/StyledScrollBar.qml b/dots/quickshell/widgets/StyledScrollBar.qml
deleted file mode 100644
index c655536..0000000
--- a/dots/quickshell/widgets/StyledScrollBar.qml
+++ /dev/null
@@ -1,34 +0,0 @@
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Controls
-
-ScrollBar {
- id: root
-
- contentItem: StyledRect {
- implicitWidth: 6
- opacity: root.pressed ? 1 : root.policy === ScrollBar.AlwaysOn || (root.active && root.size < 1) ? 0.8 : 0
- radius: Appearance.rounding.full
- color: Colours.palette.m3secondary
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- MouseArea {
- z: -1
- anchors.fill: parent
- onWheel: event => {
- if (event.angleDelta.y > 0)
- root.decrease();
- else if (event.angleDelta.y < 0)
- root.increase();
- }
- }
-}
diff --git a/dots/quickshell/widgets/StyledText.qml b/dots/quickshell/widgets/StyledText.qml
deleted file mode 100644
index 5cd4986..0000000
--- a/dots/quickshell/widgets/StyledText.qml
+++ /dev/null
@@ -1,52 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/services"
-import "root:/config"
-import QtQuick
-
-Text {
- id: root
-
- property bool animate: false
- property string animateProp: "scale"
- property real animateFrom: 0
- property real animateTo: 1
- property int animateDuration: Appearance.anim.durations.normal
-
- renderType: Text.NativeRendering
- textFormat: Text.PlainText
- color: Colours.palette.m3onSurface
- font.family: Appearance.font.family.sans
- font.pointSize: Appearance.font.size.smaller
-
- Behavior on color {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on text {
- enabled: root.animate
-
- SequentialAnimation {
- Anim {
- to: root.animateFrom
- easing.bezierCurve: Appearance.anim.curves.standardAccel
- }
- PropertyAction {}
- Anim {
- to: root.animateTo
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
- }
-
- component Anim: NumberAnimation {
- target: root
- property: root.animateProp
- duration: root.animateDuration / 2
- easing.type: Easing.BezierSpline
- }
-}
diff --git a/dots/quickshell/widgets/StyledTextField.qml b/dots/quickshell/widgets/StyledTextField.qml
deleted file mode 100644
index 1209ec1..0000000
--- a/dots/quickshell/widgets/StyledTextField.qml
+++ /dev/null
@@ -1,68 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Controls
-
-TextField {
- id: root
-
- color: Colours.palette.m3onSurface
- placeholderTextColor: Colours.palette.m3outline
- font.family: Appearance.font.family.sans
- font.pointSize: Appearance.font.size.smaller
-
- cursorDelegate: StyledRect {
- id: cursor
-
- property bool disableBlink
-
- implicitWidth: 2
- color: Colours.palette.m3primary
- radius: Appearance.rounding.normal
- onXChanged: {
- opacity = 1;
- disableBlink = true;
- enableBlink.start();
- }
-
- Timer {
- id: enableBlink
-
- interval: 100
- onTriggered: cursor.disableBlink = false
- }
-
- Timer {
- running: root.cursorVisible && !cursor.disableBlink
- repeat: true
- interval: 500
- onTriggered: parent.opacity = parent.opacity === 1 ? 0 : 1
- }
-
- Behavior on opacity {
- NumberAnimation {
- duration: Appearance.anim.durations.small
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
- }
-
- Behavior on color {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-
- Behavior on placeholderTextColor {
- ColorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/quickshell/widgets/StyledWindow.qml b/dots/quickshell/widgets/StyledWindow.qml
deleted file mode 100644
index 67280b6..0000000
--- a/dots/quickshell/widgets/StyledWindow.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import "root:/utils"
-import "root:/config"
-import Quickshell
-import Quickshell.Wayland
-
-PanelWindow {
- required property string name
-
- WlrLayershell.namespace: `caelestia-${name}`
- color: "transparent"
-}
diff --git a/dots/quickshell/widgets/VerticalSlider.qml b/dots/quickshell/widgets/VerticalSlider.qml
deleted file mode 100644
index 2b807a1..0000000
--- a/dots/quickshell/widgets/VerticalSlider.qml
+++ /dev/null
@@ -1,136 +0,0 @@
-import "root:/widgets"
-import "root:/services"
-import "root:/config"
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Effects
-
-Slider {
- id: root
-
- required property string icon
- property real oldValue
-
- orientation: Qt.Vertical
-
- background: StyledRect {
- color: Colours.alpha(Colours.palette.m3surfaceContainer, true)
- radius: Appearance.rounding.full
-
- StyledRect {
- anchors.left: parent.left
- anchors.right: parent.right
-
- y: root.handle.y
- implicitHeight: parent.height - y
-
- color: Colours.alpha(Colours.palette.m3secondary, true)
- radius: Appearance.rounding.full
- }
- }
-
- handle: Item {
- id: handle
-
- property bool moving
-
- y: root.visualPosition * (root.availableHeight - height)
- implicitWidth: root.width
- implicitHeight: root.width
-
- RectangularShadow {
- anchors.fill: parent
- radius: rect.radius
- color: Colours.palette.m3shadow
- blur: 5
- spread: 0
- }
-
- StyledRect {
- id: rect
-
- anchors.fill: parent
-
- color: Colours.alpha(Colours.palette.m3inverseSurface, true)
- radius: Appearance.rounding.full
-
- MouseArea {
- anchors.fill: parent
- cursorShape: Qt.PointingHandCursor
- onPressed: event => event.accepted = false
- }
-
- MaterialIcon {
- id: icon
-
- property bool moving: handle.moving
-
- function update(): void {
- animate = !moving;
- text = moving ? Qt.binding(() => Math.round(root.value * 100)) : Qt.binding(() => root.icon);
- font.pointSize = moving ? Appearance.font.size.small : Appearance.font.size.normal;
- font.family = moving ? Appearance.font.family.sans : Appearance.font.family.material;
- }
-
- animate: true
- text: root.icon
- color: Colours.palette.m3inverseOnSurface
- anchors.centerIn: parent
-
- Behavior on moving {
- SequentialAnimation {
- NumberAnimation {
- target: icon
- property: "scale"
- from: 1
- to: 0
- duration: Appearance.anim.durations.normal / 2
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardAccel
- }
- ScriptAction {
- script: icon.update()
- }
- NumberAnimation {
- target: icon
- property: "scale"
- from: 0
- to: 1
- duration: Appearance.anim.durations.normal / 2
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
- }
- }
- }
- }
-
- onPressedChanged: handle.moving = pressed
-
- onValueChanged: {
- if (Math.abs(value - oldValue) < 0.01)
- return;
- oldValue = value;
- handle.moving = true;
- stateChangeDelay.restart();
- }
-
- Timer {
- id: stateChangeDelay
-
- interval: 500
- onTriggered: {
- if (!root.pressed)
- handle.moving = false;
- }
- }
-
- Behavior on value {
- NumberAnimation {
- duration: Appearance.anim.durations.large
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- }
-}
diff --git a/dots/shell b/dots/shell
new file mode 160000
index 0000000..6ae4514
--- /dev/null
+++ b/dots/shell
@@ -0,0 +1 @@
+Subproject commit 6ae451413ddab08fce7326f141ee4e2508237b45
diff --git a/home/homePkgs.nix b/home/homePkgs.nix
index a85694f..81f7b39 100755
--- a/home/homePkgs.nix
+++ b/home/homePkgs.nix
@@ -209,5 +209,6 @@ in
android-tools
#grayjay
youtube-music
+ ulauncher
];
}
diff --git a/home/mrfluffy.nix b/home/mrfluffy.nix
index 7f9c177..155a538 100755
--- a/home/mrfluffy.nix
+++ b/home/mrfluffy.nix
@@ -100,7 +100,7 @@ in
{ allowUnfree = true; }
'';
#".config/doom".source = ../dots/doom;
- ".config/quickshell".source = ../dots/quickshell;
+ ".config/shell".source = ../dots/quickshell;
#".config/kitty".source = ../../universal/dots/kitty;
#".config/nvim".source = ../../universal/dots/nvim;
"Pictures/Wallpapers".source = ../assets/Wallpapers;
diff --git a/home/services.nix b/home/services.nix
index 40928f6..a383a06 100644
--- a/home/services.nix
+++ b/home/services.nix
@@ -29,4 +29,23 @@ in
WantedBy = [ "graphical-session.target" ];
};
};
+ systemd.user.services.ulauncher = {
+ Unit = {
+ Description = "Ulauncher service";
+ Documentation = [ "https://ulauncher.io/" ];
+ After = [ "graphical-session.target" ];
+ };
+
+ Service = {
+ Type = "simple";
+ BusName = "io.ulauncher.Ulauncher";
+ Environment="GDK_BACKEND=x11";
+ ExecStart = "${lib.getExe pkgs.ulauncher} --hide-window";
+ Restart = "always";
+ RestartSec = 1;
+ };
+ Install = {
+ WantedBy = [ "graphical-session.target" ];
+ };
+ };
}
diff --git a/home/work.nix b/home/work.nix
index 8ec33ff..8b68ed8 100755
--- a/home/work.nix
+++ b/home/work.nix
@@ -101,7 +101,7 @@ in
{ allowUnfree = true; }
'';
#".config/doom".source = ../dots/doom;
- ".config/quickshell".source = ../dots/quickshell;
+ ".config/shell".source = ../dots/quickshell;
#".config/kitty".source = ../../universal/dots/kitty;
#".config/nvim".source = ../../universal/dots/nvim;
"Pictures/Wallpapers".source = ../assets/Wallpapers;