diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index c3bea1d9..af524a04 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -359,13 +359,6 @@ "health": "Zustand: {percent}%", "idle": "Leerlauf.", "no-battery-detected": "Keine Batterie erkannt.", - "panel": { - "balanced": "Ausgeglichen ({percent}%)", - "disabled": "Batteriemanager deaktiviert", - "full": "Volle Kapazität ({percent}%)", - "lifespan": "Verlängerte Lebensdauer ({percent}%)", - "title": "Ladeschwelle" - }, "plugged-in": "Angeschlossen.", "time-left": "Verbleibende Zeit: {time}.", "time-until-full": "Zeit bis vollständig geladen: {time}." @@ -1867,19 +1860,6 @@ "low": "Niedriger Batteriestand", "low-desc": "Batterie ist bei {percent}%. Bitte schließen Sie das Ladegerät an." }, - "battery-manager": { - "initial-setup": "Ersteinrichtung erforderlich", - "install-failed": "Installation fehlgeschlagen", - "install-missing": "Erforderliche Dateien fehlen", - "install-success": "Erfolgreich installiert", - "install-unsupported": "System wird nicht unterstützt", - "set-failed": "Fehler beim Setzen der Batterieschwelle", - "set-success-desc": "Batterieschwelle auf {percent}% gesetzt", - "title": "Batterieschwelle", - "uninstall-failed": "Deinstallation fehlgeschlagen", - "uninstall-setup": "Deinstallation, Authentifizierung erforderlich", - "uninstall-success": "Erfolgreich deinstalliert" - }, "bluetooth": { "disabled": "Deaktiviert", "enabled": "Aktiviert" diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 4bb12882..5492048a 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -359,13 +359,6 @@ "health": "Health: {percent}%", "idle": "Idle.", "no-battery-detected": "No battery detected.", - "panel": { - "balanced": "Balanced ({percent}%)", - "disabled": "Battery manager disabled", - "full": "Full capacity ({percent}%)", - "lifespan": "Extended lifespan ({percent}%)", - "title": "Charge threshold" - }, "plugged-in": "Plugged in.", "time-left": "Time left: {time}.", "time-until-full": "Time until full: {time}." @@ -1867,19 +1860,6 @@ "low": "Low battery", "low-desc": "Battery is at {percent}%. Please connect the charger." }, - "battery-manager": { - "initial-setup": "Initial setup required", - "install-failed": "Installation failed", - "install-missing": "Required files are missing", - "install-success": "Installed successfully", - "install-unsupported": "System is not supported", - "set-failed": "Failed to set battery threshold", - "set-success-desc": "Battery threshold set to {percent}%", - "title": "Battery threshold", - "uninstall-failed": "Uninstallation failed", - "uninstall-setup": "Uninstalling, authentication required", - "uninstall-success": "Uninstalled successfully" - }, "bluetooth": { "disabled": "Disabled", "enabled": "Enabled" diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index edd81d96..b9778975 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -359,13 +359,6 @@ "health": "Salud: {percent}%", "idle": "Inactivo.", "no-battery-detected": "No se detectó ninguna batería.", - "panel": { - "balanced": "Equilibrado ({percent}%)", - "disabled": "Administrador de batería deshabilitado", - "full": "Capacidad total ({percent}%)", - "lifespan": "Vida útil prolongada ({percent}%)", - "title": "Umbral de carga" - }, "plugged-in": "Conectado.", "time-left": "Tiempo restante: {time}.", "time-until-full": "Tiempo hasta carga completa: {time}." @@ -1867,19 +1860,6 @@ "low": "Batería baja", "low-desc": "La batería está al {percent}%. Por favor, conecta el cargador." }, - "battery-manager": { - "initial-setup": "Configuración inicial requerida", - "install-failed": "Error en la instalación", - "install-missing": "Faltan archivos requeridos", - "install-success": "Instalado correctamente", - "install-unsupported": "El sistema no es compatible", - "set-failed": "No se pudo establecer el umbral de batería", - "set-success-desc": "Umbral de batería establecido en {percent}%", - "title": "Umbral de batería", - "uninstall-failed": "Error en la desinstalación", - "uninstall-setup": "Desinstalando, se requiere autenticación", - "uninstall-success": "Desinstalado correctamente" - }, "bluetooth": { "disabled": "Desactivado", "enabled": "Activado" diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 1bf56ea6..4e952a2e 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -359,13 +359,6 @@ "health": "État : {percent}%", "idle": "Inactif.", "no-battery-detected": "Aucune batterie détectée.", - "panel": { - "balanced": "Équilibré ({percent}%)", - "disabled": "Gestionnaire de batterie désactivé", - "full": "Capacité totale ({percent}%)", - "lifespan": "Durée de vie prolongée ({percent}%)", - "title": "Seuil de charge" - }, "plugged-in": "Branché.", "time-left": "Temps restant : {time}.", "time-until-full": "Temps jusqu'à charge complète : {time}." @@ -1867,19 +1860,6 @@ "low": "Batterie faible", "low-desc": "La batterie est à {percent}%. Veuillez brancher le chargeur." }, - "battery-manager": { - "initial-setup": "Configuration initiale requise", - "install-failed": "Échec de l'installation", - "install-missing": "Fichiers requis manquants", - "install-success": "Installation réussie", - "install-unsupported": "Système non pris en charge", - "set-failed": "Échec de la définition du seuil de batterie", - "set-success-desc": "Seuil de batterie défini à {percent}%", - "title": "Seuil de batterie", - "uninstall-failed": "Échec de la désinstallation", - "uninstall-setup": "Désinstallation, authentification requise", - "uninstall-success": "Désinstallation réussie" - }, "bluetooth": { "disabled": "Désactivé", "enabled": "Activé" diff --git a/Assets/Translations/nl.json b/Assets/Translations/nl.json index 1b9fc525..439bb77b 100644 --- a/Assets/Translations/nl.json +++ b/Assets/Translations/nl.json @@ -359,13 +359,6 @@ "health": "Gezondheid: {percent}%", "idle": "In rust.", "no-battery-detected": "Geen batterij gedetecteerd.", - "panel": { - "balanced": "Gebalanceerd ({percent}%)", - "disabled": "Batterijbeheer uitgeschakeld", - "full": "Volledige capaciteit ({percent}%)", - "lifespan": "Verlengde levensduur ({percent}%)", - "title": "Batterijdrempel" - }, "plugged-in": "Op netstroom.", "time-left": "Resterende tijd: {time}.", "time-until-full": "Tijd tot vol: {time}." @@ -1867,19 +1860,6 @@ "low": "Batterij bijna leeg", "low-desc": "De batterij is op {percent}%. Sluit de oplader aan." }, - "battery-manager": { - "initial-setup": "Initiële configuratie vereist", - "install-failed": "Installatie mislukt", - "install-missing": "Vereiste bestanden ontbreken", - "install-success": "Succesvol geïnstalleerd", - "install-unsupported": "Systeem wordt niet ondersteund", - "set-failed": "Instellen van batterijdrempel mislukt", - "set-success-desc": "Batterijdrempel ingesteld op {percent}%", - "title": "Batterijdrempel", - "uninstall-failed": "Deïnstallatie mislukt", - "uninstall-setup": "Verwijderen, authenticatie vereist", - "uninstall-success": "Succesvol verwijderd" - }, "bluetooth": { "disabled": "Uitgeschakeld", "enabled": "Ingeschakeld" diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 8478e198..82e67caa 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -359,13 +359,6 @@ "health": "Saúde: {percent}%", "idle": "Ocioso.", "no-battery-detected": "Nenhuma bateria detectada.", - "panel": { - "balanced": "Balanceado ({percent}%)", - "disabled": "Gerenciador de bateria desativado", - "full": "Capacidade máxima ({percent}%)", - "lifespan": "Vida útil prolongada ({percent}%)", - "title": "Limite de carga" - }, "plugged-in": "Conectado.", "time-left": "Tempo restante: {time}.", "time-until-full": "Tempo até carga completa: {time}." @@ -1867,19 +1860,6 @@ "low": "Bateria Fraca", "low-desc": "A bateria está em {percent}%. Por favor, conecte o carregador." }, - "battery-manager": { - "initial-setup": "Configuração inicial necessária", - "install-failed": "Falha na instalação", - "install-missing": "Arquivos necessários ausentes", - "install-success": "Instalado com sucesso", - "install-unsupported": "Sistema não suportado", - "set-failed": "Falha ao definir o limite da bateria", - "set-success-desc": "Limite da bateria definido para {percent}%", - "title": "Limite da bateria", - "uninstall-failed": "Falha na desinstalação", - "uninstall-setup": "Desinstalando, autenticação necessária", - "uninstall-success": "Desinstalado com sucesso" - }, "bluetooth": { "disabled": "Desativado", "enabled": "Ativado" diff --git a/Assets/Translations/ru.json b/Assets/Translations/ru.json index 170fcc43..0c977e8e 100644 --- a/Assets/Translations/ru.json +++ b/Assets/Translations/ru.json @@ -359,13 +359,6 @@ "health": "Здоровье: {percent}%", "idle": "Простой.", "no-battery-detected": "Батарея не обнаружена.", - "panel": { - "balanced": "Сбалансированный ({percent}%)", - "disabled": "Диспетчер батареи отключен", - "full": "Полная емкость ({percent}%)", - "lifespan": "Увеличенный срок службы ({percent}%)", - "title": "Порог зарядки" - }, "plugged-in": "Подключено.", "time-left": "Осталось времени: {time}.", "time-until-full": "Время до полной зарядки: {time}." @@ -1867,19 +1860,6 @@ "low": "Низкий заряд батареи", "low-desc": "Заряд батареи {percent}%. Пожалуйста, подключите зарядное устройство." }, - "battery-manager": { - "initial-setup": "Требуется начальная настройка", - "install-failed": "Сбой установки", - "install-missing": "Отсутствуют необходимые файлы", - "install-success": "Успешно установлено", - "install-unsupported": "Система не поддерживается", - "set-failed": "Не удалось установить порог зарядки батареи", - "set-success-desc": "Порог зарядки батареи установлен на {percent}%", - "title": "Порог зарядки батареи", - "uninstall-failed": "Сбой удаления", - "uninstall-setup": "Удаление, требуется аутентификация", - "uninstall-success": "Успешно удалено" - }, "bluetooth": { "disabled": "Отключен", "enabled": "Включен" diff --git a/Assets/Translations/tr.json b/Assets/Translations/tr.json index 88ada2e1..e24cd08b 100644 --- a/Assets/Translations/tr.json +++ b/Assets/Translations/tr.json @@ -359,13 +359,6 @@ "health": "Sağlık: {percent}%", "idle": "Boşta.", "no-battery-detected": "Pil tespit edilmedi.", - "panel": { - "balanced": "Dengeli ({percent}%)", - "disabled": "Pil yöneticisi devre dışı", - "full": "Tam kapasite ({percent}%)", - "lifespan": "Uzatılmış ömür ({percent}%)", - "title": "Şarj eşiği" - }, "plugged-in": "Prize takılı.", "time-left": "Kalan süre: {time}.", "time-until-full": "Dolma süresi: {time}." @@ -1867,19 +1860,6 @@ "low": "Düşük batarya", "low-desc": "Batarya % {percent}. Lütfen şarj bağlantısını yapın." }, - "battery-manager": { - "initial-setup": "Başlangıç kurulumu gerekli", - "install-failed": "Kurulum başarısız oldu", - "install-missing": "Gerekli dosyalar eksik", - "install-success": "Başarıyla kuruldu", - "install-unsupported": "Sistem desteklenmiyor", - "set-failed": "Batarya eşiği ayarlanamadı", - "set-success-desc": "Batarya eşiği % {percent} olarak ayarlandı", - "title": "Batarya eşiği", - "uninstall-failed": "Kaldırma başarısız oldu", - "uninstall-setup": "Kaldırılıyor, kimlik doğrulama gerekli", - "uninstall-success": "Başarıyla kaldırıldı" - }, "bluetooth": { "disabled": "Devre dışı", "enabled": "Etkin" diff --git a/Assets/Translations/uk-UA.json b/Assets/Translations/uk-UA.json index f5a3033c..d7220b6e 100644 --- a/Assets/Translations/uk-UA.json +++ b/Assets/Translations/uk-UA.json @@ -359,13 +359,6 @@ "health": "Здоров'я: {percent}%", "idle": "Бездіяльність.", "no-battery-detected": "Батарею не виявлено.", - "panel": { - "balanced": "Збалансований ({percent}%)", - "disabled": "Менеджер батареї вимкнено", - "full": "Повна ємність ({percent}%)", - "lifespan": "Подовжений термін служби ({percent}%)", - "title": "Поріг зарядки" - }, "plugged-in": "Підключено.", "time-left": "Залишилось часу: {time}.", "time-until-full": "Час до повного заряду: {time}." @@ -1867,19 +1860,6 @@ "low": "Низький заряд батареї", "low-desc": "Батарея на {percent}%. Будь ласка, підключіть зарядний пристрій." }, - "battery-manager": { - "initial-setup": "Потрібне початкове налаштування", - "install-failed": "Помилка встановлення", - "install-missing": "Необхідні файли відсутні", - "install-success": "Встановлено успішно", - "install-unsupported": "Система не підтримується", - "set-failed": "Не вдалося встановити поріг батареї", - "set-success-desc": "Поріг батареї встановлено на {percent}%", - "title": "Поріг батареї", - "uninstall-failed": "Помилка видалення", - "uninstall-setup": "Видалення, потрібна автентифікація", - "uninstall-success": "Видалено успішно" - }, "bluetooth": { "disabled": "Вимкнено", "enabled": "Увімкнено" diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 020f9b52..631846a2 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -359,13 +359,6 @@ "health": "健康状况:{percent}%", "idle": "空闲。", "no-battery-detected": "未检测到电池。", - "panel": { - "balanced": "平衡 ({percent}%)", - "disabled": "电池管理器已禁用", - "full": "完全容量 ({percent}%)", - "lifespan": "延长寿命 ({percent}%)", - "title": "充电阈值" - }, "plugged-in": "已接通电源。", "time-left": "剩余时间:{time}。", "time-until-full": "充满所需时间:{time}。" @@ -1867,19 +1860,6 @@ "low": "电量低", "low-desc": "电量为 {percent}%。请连接充电器。" }, - "battery-manager": { - "initial-setup": "需要初始设置", - "install-failed": "安装失败", - "install-missing": "缺少必要文件", - "install-success": "安装成功", - "install-unsupported": "系统不受支持", - "set-failed": "设置电池阈值失败", - "set-success-desc": "电池阈值已设置为 {percent}%", - "title": "电池阈值", - "uninstall-failed": "卸载失败", - "uninstall-setup": "正在卸载,需要身份验证", - "uninstall-success": "卸载成功" - }, "bluetooth": { "disabled": "已禁用", "enabled": "已启用" diff --git a/Bin/battery-manager/battery-paths.conf b/Bin/battery-manager/battery-paths.conf deleted file mode 100644 index 3a539237..00000000 --- a/Bin/battery-manager/battery-paths.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Battery charge control paths -# Add one path per line -/sys/class/power_supply/BAT0/charge_control_end_threshold -/sys/class/power_supply/BAT1/charge_control_end_threshold -/sys/class/power_supply/BAT0/charge_stop_threshold diff --git a/Bin/battery-manager/install-battery-manager.sh b/Bin/battery-manager/install-battery-manager.sh deleted file mode 100755 index 36315d15..00000000 --- a/Bin/battery-manager/install-battery-manager.sh +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env bash -set -e - -SUCCESS=0 -FAILURE=1 -MISSING_FILES=2 -UNSUPPORTED=3 - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -print_error() { - echo -e "$1" >&2 -} - -print_info() { - echo -e "$1" -} - -if [ "$EUID" -ne 0 ]; then - print_error "This script must be run with root privileges" - exit $FAILURE -fi - -print_info "Installing Battery Manager..." -echo - -if [ -n "$PKEXEC_UID" ]; then - ACTUAL_USER=$(getent passwd "$PKEXEC_UID" | cut -d: -f1) -else - ACTUAL_USER="$SUDO_USER" -fi - -if [ -z "$ACTUAL_USER" ]; then - print_error "Could not determine the actual user" - exit $FAILURE -fi - -print_info "Installing for user: $ACTUAL_USER" -echo - -print_info "Checking required files..." - -MISSING_FILES_LIST=() - -if [ ! -f "$SCRIPT_DIR/battery-paths.conf" ]; then - MISSING_FILES_LIST+=("battery-paths.conf") -fi - -if [ ! -f "$SCRIPT_DIR/templates/battery-manager.sh" ]; then - MISSING_FILES_LIST+=("battery-manager.sh") -fi - -if [ ! -f "$SCRIPT_DIR/templates/battery-manager.policy" ]; then - MISSING_FILES_LIST+=("battery-manager.policy") -fi - -if [ ! -f "$SCRIPT_DIR/templates/battery-manager.rules" ]; then - MISSING_FILES_LIST+=("battery-manager.rules") -fi - -if [ ${#MISSING_FILES_LIST[@]} -gt 0 ]; then - print_error "Missing required files in $SCRIPT_DIR:" - for file in "${MISSING_FILES_LIST[@]}"; do - print_error " - $file" - done - exit $MISSING_FILES -fi - -print_info "All required files found" - -print_info "Checking battery paths..." -BATTERY_PATHS=($(grep -v '^#' "$SCRIPT_DIR/battery-paths.conf" | grep -v '^$')) -EXISTING_PATHS=() - -for path in "${BATTERY_PATHS[@]}"; do - if [ -f "$path" ]; then - EXISTING_PATHS+=("$path") - fi -done - -if [ ${#EXISTING_PATHS[@]} -eq 0 ]; then - print_error "None of the battery control files exist. Please check your hardware compatibility." - exit $UNSUPPORTED -fi - -print_info "Found ${#EXISTING_PATHS[@]} compatible battery control file(s)" - -print_info "Installing battery manager script..." -BATTERY_MANAGER_SCRIPT="/usr/bin/battery-manager-$ACTUAL_USER" - -SHEBANG=$(head -n 1 "$SCRIPT_DIR/templates/battery-manager.sh") -echo "$SHEBANG" > "$BATTERY_MANAGER_SCRIPT" -echo "" >> "$BATTERY_MANAGER_SCRIPT" - -echo "BATTERY_PATHS=(" >> "$BATTERY_MANAGER_SCRIPT" -for path in "${EXISTING_PATHS[@]}"; do - echo " \"$path\"" >> "$BATTERY_MANAGER_SCRIPT" -done -echo ")" >> "$BATTERY_MANAGER_SCRIPT" - -echo "" >> "$BATTERY_MANAGER_SCRIPT" - -tail -n +2 "$SCRIPT_DIR/templates/battery-manager.sh" >> "$BATTERY_MANAGER_SCRIPT" - -chmod +x "$BATTERY_MANAGER_SCRIPT" - -print_info "Battery manager script created from $SCRIPT_DIR/templates/battery-manager.sh with compatible paths" -print_info "Script installed at $BATTERY_MANAGER_SCRIPT" - -print_info "Creating log file..." -touch /var/log/battery-manager.log -chmod 644 /var/log/battery-manager.log -print_info "Log file created at /var/log/battery-manager.log" - -print_info "Creating polkit policy..." - -POLICY_FILE="/usr/share/polkit-1/actions/com.local.battery-manager.$ACTUAL_USER.policy" - -sed -e "s/ACTUAL_USER_PLACEHOLDER/$ACTUAL_USER/g" \ - "$SCRIPT_DIR/templates/battery-manager.policy" > "$POLICY_FILE" - -print_info "Polkit policy copied from $SCRIPT_DIR/templates/battery-manager.policy" -print_info "Polkit policy created at $POLICY_FILE" -print_info "Creating polkit rule..." - -RULES_FILE="/etc/polkit-1/rules.d/50-battery-manager-$ACTUAL_USER.rules" - -sed "s/ACTUAL_USER_PLACEHOLDER/$ACTUAL_USER/g" \ - "$SCRIPT_DIR/templates/battery-manager.rules" > "$RULES_FILE" - -print_info "Polkit rule copied from $SCRIPT_DIR/templates/battery-manager.rules" -print_info "Polkit rule created for user: $ACTUAL_USER at $RULES_FILE" - -print_info "Restarting polkit..." -if systemctl restart polkit 2>/dev/null; then - print_info "Polkit restarted" -else - print_info "Could not restart polkit automatically, you may need to reboot" -fi - -print_info "Creating uninstall script..." -UNINSTALL_SCRIPT="$SCRIPT_DIR/uninstall-battery-manager.sh" - - -if [ -f "$SCRIPT_DIR/templates/uninstall-template" ]; then - SHEBANG=$(head -n 1 "$SCRIPT_DIR/templates/uninstall-template") -else - SHEBANG="#!/usr/bin/env bash" -fi -echo "$SHEBANG" > "$UNINSTALL_SCRIPT" -echo "" >> "$UNINSTALL_SCRIPT" - -cat >> "$UNINSTALL_SCRIPT" << EOF -SCRIPT_PATH="$BATTERY_MANAGER_SCRIPT" -POLICY_PATH="$POLICY_FILE" -RULE_PATH="$RULES_FILE" -LOG_PATH="/var/log/battery-manager.log" - -EOF - -if [ -f "$SCRIPT_DIR/templates/uninstall-template" ]; then - tail -n +2 "$SCRIPT_DIR/templates/uninstall-template" >> "$UNINSTALL_SCRIPT" -fi - -chmod 744 "$UNINSTALL_SCRIPT" -chown root:root "$UNINSTALL_SCRIPT" - -print_info "Uninstall script created at $UNINSTALL_SCRIPT" - - -echo -print_info "Installation complete!" -echo -print_info "Log file: /var/log/battery-manager.log" -print_info "User-specific script: $BATTERY_MANAGER_SCRIPT" -print_info "User-specific policy: $POLICY_FILE" -print_info "User-specific rules: $RULES_FILE" -print_info "User-specific uninstall script: $UNINSTALL_SCRIPT" diff --git a/Bin/battery-manager/set-battery-treshold.sh b/Bin/battery-manager/set-battery-treshold.sh deleted file mode 100755 index defcc7f1..00000000 --- a/Bin/battery-manager/set-battery-treshold.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env bash - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SUPPRESS_NOTIFICATIONS=false - -print_error() { - echo -e "$1" >&2 -} - -print_info() { - echo -e "$1" -} - -send_notification() { - local urgency="$1" - local title="$2" - local message="$3" - - if [ "$SUPPRESS_NOTIFICATIONS" = false ] && command -v notify-send >/dev/null 2>&1; then - notify-send -u "$urgency" "$title" "$message" - fi -} - -while [[ $# -gt 0 ]]; do - case "$1" in - -q|--quiet) - SUPPRESS_NOTIFICATIONS=true - shift - ;; - -*) - print_error "Unknown option: $1" - echo "Usage: $0 [OPTIONS] " >&2 - echo "Options:" >&2 - echo " -q, --quiet Suppress notifications" >&2 - exit 1 - ;; - *) - BATTERY_LEVEL="$1" - shift - ;; - esac -done - -if [ -z "$BATTERY_LEVEL" ]; then - print_error "Battery level not specified" - echo "Usage: $0 [OPTIONS] " >&2 - echo "Options:" >&2 - echo " -q, --quiet Suppress notifications" >&2 - exit 1 -fi - -if ! [[ "$BATTERY_LEVEL" =~ ^[0-9]+$ ]] || [ "$BATTERY_LEVEL" -gt 100 ] || [ "$BATTERY_LEVEL" -lt 0 ]; then - print_error "Battery level must be a number between 0-100" - echo "Usage: $0 [OPTIONS] " >&2 - echo "Options:" >&2 - echo " -q, --quiet Suppress notifications" >&2 - exit 1 -fi - -CURRENT_USER="$USER" -if [ -z "$CURRENT_USER" ]; then - CURRENT_USER="$(whoami)" -fi - -BATTERY_MANAGER_PATH="/usr/bin/battery-manager-$CURRENT_USER" - -SUCCESS=0 -MISSING_FILES=2 - -if [ ! -f "$BATTERY_MANAGER_PATH" ]; then - print_error "Battery manager components missing for user $CURRENT_USER!" - exit $MISSING_FILES -fi - -print_info "Setting battery charging threshold to $BATTERY_LEVEL% for user $CURRENT_USER..." - -if pkexec "$BATTERY_MANAGER_PATH" "$BATTERY_LEVEL"; then - print_info "Battery charging threshold set to $BATTERY_LEVEL%" - send_notification "normal" "Battery Threshold Updated" \ - "Battery charging threshold has been set to $BATTERY_LEVEL%" -else - print_error "Failed to set battery charging threshold" - send_notification "critical" "Battery Threshold Failed" \ - "Failed to set battery charging threshold to $BATTERY_LEVEL%" - exit 1 -fi diff --git a/Bin/battery-manager/templates/battery-manager.policy b/Bin/battery-manager/templates/battery-manager.policy deleted file mode 100644 index 78473a7a..00000000 --- a/Bin/battery-manager/templates/battery-manager.policy +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Manage battery settings for ACTUAL_USER_PLACEHOLDER - Authentication is required to manage battery settings - - no - no - yes - - /usr/bin/battery-manager-ACTUAL_USER_PLACEHOLDER - true - - diff --git a/Bin/battery-manager/templates/battery-manager.rules b/Bin/battery-manager/templates/battery-manager.rules deleted file mode 100644 index 6e927653..00000000 --- a/Bin/battery-manager/templates/battery-manager.rules +++ /dev/null @@ -1,14 +0,0 @@ -polkit.addRule(function(action, subject) { - if (action.id == "com.local.battery-manager.ACTUAL_USER_PLACEHOLDER" && - subject.user == "ACTUAL_USER_PLACEHOLDER") { - - // Check if the parent process is quickshell or set-battery-threshold - var pid = subject.pid; - var ppid = polkit.spawn(["ps", "-o", "ppid=", "-p", pid.toString()]).trim(); - var parentCmd = polkit.spawn(["ps", "-o", "comm=", "-p", ppid]).trim(); - - if (parentCmd.indexOf("quickshell") !== -1 || parentCmd.indexOf("set-battery-treshold") !== -1) { - return polkit.Result.YES; - } - } -}); diff --git a/Bin/battery-manager/templates/battery-manager.sh b/Bin/battery-manager/templates/battery-manager.sh deleted file mode 100644 index 41e551b0..00000000 --- a/Bin/battery-manager/templates/battery-manager.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash - -LOG_FILE="/var/log/battery-manager.log" - -log_message() { - echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" -} - -if [ -z "$1" ]; then - echo "Error: No battery level provided" >&2 - log_message "ERROR: No battery level provided" - exit 1 -fi - -BATTERY_LEVEL="$1" - -if ! [[ "$BATTERY_LEVEL" =~ ^[0-9]+$ ]] || [ "$BATTERY_LEVEL" -gt 100 ] || [ "$BATTERY_LEVEL" -lt 0 ]; then - echo "Error: Invalid battery level. Must be 0-100" >&2 - log_message "ERROR: Invalid battery level: $BATTERY_LEVEL" - exit 1 -fi - -SUCCESS_COUNT=0 -FAIL_COUNT=0 - -for path in "${BATTERY_PATHS[@]}"; do - [[ -z "$path" || "$path" =~ ^# ]] && continue - - if [ -f "$path" ] && [ -w "$path" ]; then - if echo "$BATTERY_LEVEL" > "$path" 2>/dev/null; then - echo "Updated: $path" - log_message "SUCCESS: Updated $path to $BATTERY_LEVEL" - ((SUCCESS_COUNT++)) - else - echo "Failed to write: $path" >&2 - log_message "ERROR: Failed to write to $path" - ((FAIL_COUNT++)) - fi - else - echo "Skipped (not found/writable): $path" - log_message "INFO: Skipped $path (not found or not writable)" - fi -done - -log_message "SUMMARY: Updated $SUCCESS_COUNT file(s), failed $FAIL_COUNT, battery level: $BATTERY_LEVEL" - -if [ "$SUCCESS_COUNT" -eq 0 ]; then - echo "Error: No battery files were updated" >&2 - exit 1 -fi - -echo "Successfully updated $SUCCESS_COUNT battery file(s)" -exit 0 diff --git a/Bin/battery-manager/templates/uninstall-template b/Bin/battery-manager/templates/uninstall-template deleted file mode 100644 index f2cf83eb..00000000 --- a/Bin/battery-manager/templates/uninstall-template +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -if [ "$(id -u)" -ne 0 ]; then - echo "This script must be run as root" - exit 1 -fi - -echo "Uninstalling battery manager..." - -if [ -f "$SCRIPT_PATH" ]; then - rm -f "$SCRIPT_PATH" - echo "Removed script from $SCRIPT_PATH" -fi - -if [ -f "$POLICY_PATH" ]; then - rm -f "$POLICY_PATH" - echo "Removed policy file from $POLICY_PATH" -fi - -if [ -f "$RULE_PATH" ]; then - rm -f "$RULE_PATH" - echo "Removed udev rule from $RULE_PATH" -fi - -if [ -f "$LOG_PATH" ]; then - rm -f "$LOG_PATH" - echo "Removed log file from $LOG_PATH" -fi - -echo "Uninstallation completed successfully" diff --git a/Bin/test-notification-replace.sh b/Bin/dev/notifications-test-replace.sh similarity index 100% rename from Bin/test-notification-replace.sh rename to Bin/dev/notifications-test-replace.sh diff --git a/Bin/dev/qmlfmt.sh b/Bin/dev/qmlfmt.sh index 92151360..eee5bc5e 100755 --- a/Bin/dev/qmlfmt.sh +++ b/Bin/dev/qmlfmt.sh @@ -2,38 +2,28 @@ set -euo pipefail # QML Formatter Script -# Uses: https://github.com/jesperhh/qmlfmt -# Install: AUR package "qmlfmt-git" (requires qt6-5compat) -if command -v qmlfmt &>/dev/null; then - echo "Using 'qmlfmt' for formatting." - format_file() { qmlfmt -e -b 360 -t 2 -i 2 -w "$1" || { echo "Failed: $1" >&2; return 1; }; } +# Find qmlformat binary +if command -v qmlformat &>/dev/null; then + QMLFORMAT="qmlformat" +elif [ -x "/usr/lib/qt6/bin/qmlformat" ]; then + QMLFORMAT="/usr/lib/qt6/bin/qmlformat" else - echo "No 'qmlfmt' found in PATH." >&2 + echo "No 'qmlformat' found in PATH or /usr/lib/qt6/bin." >&2 exit 1 fi +echo "Using 'qmlformat' for formatting: $QMLFORMAT" +export QMLFORMAT +format_file() { "$QMLFORMAT" -w 2 -W 360 -S --semicolon-rule always -i "$1" || { echo "Failed: $1" >&2; return 1; }; } + export -f format_file # Find all .qml files mapfile -t all_files < <(find "${1:-.}" -name "*.qml" -type f) [ ${#all_files[@]} -eq 0 ] && { echo "No QML files found"; exit 0; } -echo "Scanning ${#all_files[@]} files for array destructuring..." -safe_files=() -for file in "${all_files[@]}"; do - # Checks for a comma inside brackets followed by an equals sign aka "array destructuring" - # as this ES6 syntax is not supported by qmlfmt and will result in breakage. - if grep -qE '\[.*,.*\]\s*=' "$file"; then - echo "-> Skipping (Array destructuring detected): $file" >&2 - else - safe_files+=("$file") - fi -done - -[ ${#safe_files[@]} -eq 0 ] && { echo "No safe files to format after filtering."; exit 0; } - -echo "Formatting ${#safe_files[@]} files..." -printf '%s\0' "${safe_files[@]}" | \ +echo "Formatting ${#all_files[@]} files..." +printf '%s\0' "${all_files[@]}" | \ xargs -0 -P "${QMLFMT_JOBS:-$(nproc)}" -I {} bash -c 'format_file "$@"' _ {} \ && echo "Done" || { echo "Errors occurred" >&2; exit 1; } \ No newline at end of file diff --git a/Commons/Color.qml b/Commons/Color.qml index 1e358344..c5023e8c 100644 --- a/Commons/Color.qml +++ b/Commons/Color.qml @@ -5,111 +5,80 @@ import Quickshell import Quickshell.Io import qs.Commons - /* - Noctalia is not strictly a Material Design project, it supports both some predefined - color schemes and dynamic color generation from the wallpaper (using Matugen). +Noctalia is not strictly a Material Design project, it supports both some predefined +color schemes and dynamic color generation from the wallpaper (using Matugen). - We ultimately decided to use a restricted set of colors that follows the - Material Design 3 naming convention. +We ultimately decided to use a restricted set of colors that follows the +Material Design 3 naming convention. - NOTE: All color names are prefixed with 'm' (e.g., mPrimary) to prevent QML from - misinterpreting them as signals (e.g., the 'onPrimary' property name). +NOTE: All color names are prefixed with 'm' (e.g., mPrimary) to prevent QML from +misinterpreting them as signals (e.g., the 'onPrimary' property name). */ Singleton { id: root // --- Key Colors: These are the main accent colors that define your app's style - property color mPrimary: customColors.mPrimary - property color mOnPrimary: customColors.mOnPrimary - property color mSecondary: customColors.mSecondary - property color mOnSecondary: customColors.mOnSecondary - property color mTertiary: customColors.mTertiary - property color mOnTertiary: customColors.mOnTertiary + readonly property color mPrimary: customColorsData.mPrimary + readonly property color mOnPrimary: customColorsData.mOnPrimary + readonly property color mSecondary: customColorsData.mSecondary + readonly property color mOnSecondary: customColorsData.mOnSecondary + readonly property color mTertiary: customColorsData.mTertiary + readonly property color mOnTertiary: customColorsData.mOnTertiary // --- Utility Colors: These colors serve specific, universal purposes like indicating errors - property color mError: customColors.mError - property color mOnError: customColors.mOnError + readonly property color mError: customColorsData.mError + readonly property color mOnError: customColorsData.mOnError // --- Surface and Variant Colors: These provide additional options for surfaces and their contents, creating visual hierarchy - property color mSurface: customColors.mSurface - property color mOnSurface: customColors.mOnSurface + readonly property color mSurface: customColorsData.mSurface + readonly property color mOnSurface: customColorsData.mOnSurface - property color mSurfaceVariant: customColors.mSurfaceVariant - property color mOnSurfaceVariant: customColors.mOnSurfaceVariant + readonly property color mSurfaceVariant: customColorsData.mSurfaceVariant + readonly property color mOnSurfaceVariant: customColorsData.mOnSurfaceVariant - property color mOutline: customColors.mOutline - property color mShadow: customColors.mShadow + readonly property color mOutline: customColorsData.mOutline + readonly property color mShadow: customColorsData.mShadow - property color mHover: customColors.mHover - property color mOnHover: customColors.mOnHover + readonly property color mHover: customColorsData.mHover + readonly property color mOnHover: customColorsData.mOnHover // --- Absolute Colors - property color transparent: "transparent" - property color black: "#000000" - property color white: "#ffffff" + readonly property color transparent: "transparent" + readonly property color black: "#000000" + readonly property color white: "#ffffff" // -------------------------------- // Default colors: RosePine QtObject { id: defaultColors - property color mPrimary: "#c7a1d8" - property color mOnPrimary: "#1a151f" + readonly property color mPrimary: "#c7a1d8" + readonly property color mOnPrimary: "#1a151f" - property color mSecondary: "#a984c4" - property color mOnSecondary: "#f3edf7" + readonly property color mSecondary: "#a984c4" + readonly property color mOnSecondary: "#f3edf7" - property color mTertiary: "#e0b7c9" - property color mOnTertiary: "#20161f" + readonly property color mTertiary: "#e0b7c9" + readonly property color mOnTertiary: "#20161f" - property color mError: "#e9899d" - property color mOnError: "#1e1418" + readonly property color mError: "#e9899d" + readonly property color mOnError: "#1e1418" - property color mSurface: "#1c1822" - property color mOnSurface: "#e9e4f0" + readonly property color mSurface: "#1c1822" + readonly property color mOnSurface: "#e9e4f0" - property color mSurfaceVariant: "#262130" - property color mOnSurfaceVariant: "#a79ab0" + readonly property color mSurfaceVariant: "#262130" + readonly property color mOnSurfaceVariant: "#a79ab0" - property color mOutline: "#342c42" - property color mShadow: "#120f18" + readonly property color mOutline: "#342c42" + readonly property color mShadow: "#120f18" - property color mHover: "#e0b7c9" - property color mOnHover: "#20161f" + readonly property color mHover: "#e0b7c9" + readonly property color mOnHover: "#20161f" } // ---------------------------------------------------------------- - // Custom colors loaded from colors.json - // These can be generated by matugen or simply come from a well know color scheme (Dracula, Gruvbox, Nord, ...) - QtObject { - id: customColors - - property color mPrimary: customColorsData.mPrimary - property color mOnPrimary: customColorsData.mOnPrimary - - property color mSecondary: customColorsData.mSecondary - property color mOnSecondary: customColorsData.mOnSecondary - - property color mTertiary: customColorsData.mTertiary - property color mOnTertiary: customColorsData.mOnTertiary - - property color mError: customColorsData.mError - property color mOnError: customColorsData.mOnError - - property color mSurface: customColorsData.mSurface - property color mOnSurface: customColorsData.mOnSurface - - property color mSurfaceVariant: customColorsData.mSurfaceVariant - property color mOnSurfaceVariant: customColorsData.mOnSurfaceVariant - - property color mOutline: customColorsData.mOutline - property color mShadow: customColorsData.mShadow - - property color mHover: customColorsData.mHover - property color mOnHover: customColorsData.mOnHover - } - // FileView to load custom colors data from colors.json FileView { id: customColorsFile @@ -117,24 +86,25 @@ Singleton { printErrors: false watchChanges: true onFileChanged: { - Logger.i("Color", "Reloading colors from disk") - reload() + Logger.i("Color", "Reloading colors from disk"); + reload(); } onAdapterUpdated: { - Logger.i("Color", "Writing colors to disk") - writeAdapter() + Logger.i("Color", "Writing colors to disk"); + writeAdapter(); } // Trigger initial load when path changes from empty to actual path onPathChanged: { if (path !== undefined) { - reload() + reload(); } } onLoadFailed: function (error) { - if (error.toString().includes("No such file") || error === 2) { + // Error code 2 = ENOENT (No such file or directory) + if (error === 2 || error.toString().includes("No such file")) { // File doesn't exist, create it with default values - writeAdapter() + writeAdapter(); } } JsonAdapter { diff --git a/Commons/I18n.qml b/Commons/I18n.qml index ebc1621e..433e379b 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -33,13 +33,13 @@ Singleton { onExited: function (exitCode, exitStatus) { if (exitCode === 0) { - var output = stdoutCollector.text || "" - parseDirectoryListing(output) + var output = stdoutCollector.text || ""; + parseDirectoryListing(output); } else { - Logger.e("I18n", `Failed to scan translation directory`) + Logger.e("I18n", `Failed to scan translation directory`); // Fallback to default languages - availableLanguages = ["en"] - detectLanguage() + availableLanguages = ["en"]; + detectLanguage(); } } } @@ -51,21 +51,21 @@ Singleton { onFileChanged: reload() onLoaded: { try { - var data = JSON.parse(text()) - root.translations = data - Logger.i("I18n", `Loaded translations for "${root.langCode}"`) - Logger.d("I18n", `Available root keys: ${Object.keys(data).join(", ")}`) + var data = JSON.parse(text()); + root.translations = data; + Logger.i("I18n", `Loaded translations for "${root.langCode}"`); + Logger.d("I18n", `Available root keys: ${Object.keys(data).join(", ")}`); - root.isLoaded = true - root.translationsLoaded() + root.isLoaded = true; + root.translationsLoaded(); } catch (e) { - Logger.e("I18n", `Failed to parse translation file: ${e}`) - setLanguage("en") + Logger.e("I18n", `Failed to parse translation file: ${e}`); + setLanguage("en"); } } onLoadFailed: function (error) { - setLanguage("en") - Logger.e("I18n", `Failed to load translation file: ${error}`) + setLanguage("en"); + Logger.e("I18n", `Failed to load translation file: ${error}`); } } @@ -76,162 +76,161 @@ Singleton { onFileChanged: reload() onLoaded: { try { - var data = JSON.parse(text()) - root.fallbackTranslations = data - Logger.d("I18n", `Loaded english fallback translations`) + var data = JSON.parse(text()); + root.fallbackTranslations = data; + Logger.d("I18n", `Loaded english fallback translations`); } catch (e) { - Logger.e("I18n", `Failed to parse fallback translation file: ${e}`) + Logger.e("I18n", `Failed to parse fallback translation file: ${e}`); } } onLoadFailed: function (error) { - Logger.e("I18n", `Failed to load fallback translation file: ${error}`) + Logger.e("I18n", `Failed to load fallback translation file: ${error}`); } } Component.onCompleted: { - Logger.i("I18n", "Service started") - scanAvailableLanguages() + Logger.i("I18n", "Service started"); + scanAvailableLanguages(); } // ------------------------------------------- function scanAvailableLanguages() { - Logger.d("I18n", "Scanning for available translation files...") - directoryScanner.running = true + Logger.d("I18n", "Scanning for available translation files..."); + directoryScanner.running = true; } // ------------------------------------------- function parseDirectoryListing(output) { - var languages = [] + var languages = []; try { if (!output || output.trim() === "") { - Logger.w("I18n", "Empty directory listing output") - availableLanguages = ["en"] - detectLanguage() - return + Logger.w("I18n", "Empty directory listing output"); + availableLanguages = ["en"]; + detectLanguage(); + return; } - const entries = output.trim().split('\n') + const entries = output.trim().split('\n'); for (var i = 0; i < entries.length; i++) { - const entry = entries[i].trim() + const entry = entries[i].trim(); if (entry && entry.endsWith('.json')) { // Extract language code from filename (e.g., "en.json" -> "en") - const langCode = entry.substring(0, entry.lastIndexOf('.json')) + const langCode = entry.substring(0, entry.lastIndexOf('.json')); if (langCode.length >= 2 && langCode.length <= 5) { // Basic validation for language codes - languages.push(langCode) + languages.push(langCode); } } } // Sort languages alphabetically, but ensure "en" comes first if available - languages.sort() - const enIndex = languages.indexOf("en") + languages.sort(); + const enIndex = languages.indexOf("en"); if (enIndex > 0) { - languages.splice(enIndex, 1) - languages.unshift("en") + languages.splice(enIndex, 1); + languages.unshift("en"); } if (languages.length === 0) { - Logger.w("I18n", "No translation files found, using fallback") - languages = ["en"] // Fallback + Logger.w("I18n", "No translation files found, using fallback"); + languages = ["en"]; // Fallback } - availableLanguages = languages - Logger.d("I18n", `Found ${languages.length} available languages: ${languages.join(', ')}`) + availableLanguages = languages; + Logger.d("I18n", `Found ${languages.length} available languages: ${languages.join(', ')}`); // Detect language after scanning - detectLanguage() + detectLanguage(); } catch (e) { - Logger.e("I18n", `Failed to parse directory listing: ${e}`) + Logger.e("I18n", `Failed to parse directory listing: ${e}`); // Fallback to default languages - availableLanguages = ["en"] - detectLanguage() + availableLanguages = ["en"]; + detectLanguage(); } } // ------------------------------------------- function detectLanguage() { - Logger.d("I18n", `detectLanguage() called. Available languages: [${availableLanguages.join(', ')}]`) + Logger.d("I18n", `detectLanguage() called. Available languages: [${availableLanguages.join(', ')}]`); if (availableLanguages.length === 0) { - Logger.w("I18n", "No available languages found") - return + Logger.w("I18n", "No available languages found"); + return; } - var detectedLang = "" - var detectedFullLocale = "" + var detectedLang = ""; + var detectedFullLocale = ""; // First, determine the system's preferred language for (var i = 0; i < Qt.locale().uiLanguages.length; i++) { - const fullUserLang = Qt.locale().uiLanguages[i] + const fullUserLang = Qt.locale().uiLanguages[i]; if (availableLanguages.includes(fullUserLang)) { - detectedLang = fullUserLang - detectedFullLocale = fullUserLang - break + detectedLang = fullUserLang; + detectedFullLocale = fullUserLang; + break; } - const shortUserLang = fullUserLang.substring(0, 2) + const shortUserLang = fullUserLang.substring(0, 2); if (availableLanguages.includes(shortUserLang)) { - detectedLang = shortUserLang - detectedFullLocale = fullUserLang - break + detectedLang = shortUserLang; + detectedFullLocale = fullUserLang; + break; } } // If no system language is found among available languages, fallback if (detectedLang === "") { - detectedLang = availableLanguages.includes("en") ? "en" : availableLanguages[0] - detectedFullLocale = detectedLang + detectedLang = availableLanguages.includes("en") ? "en" : availableLanguages[0]; + detectedFullLocale = detectedLang; } - root.systemDetectedLangCode = detectedLang - root.fullLocaleCode = detectedFullLocale - Logger.d("I18n", `System detected language: "${root.systemDetectedLangCode}" (full locale: "${root.fullLocaleCode}")`) + root.systemDetectedLangCode = detectedLang; + root.fullLocaleCode = detectedFullLocale; + Logger.d("I18n", `System detected language: "${root.systemDetectedLangCode}" (full locale: "${root.fullLocaleCode}")`); // Now, apply the language: user-defined, then system-detected if (Settings.data.general.language !== "" && availableLanguages.includes(Settings.data.general.language)) { - Logger.d("I18n", `User-defined language found: "${Settings.data.general.language}"`) - setLanguage(Settings.data.general.language) + Logger.d("I18n", `User-defined language found: "${Settings.data.general.language}"`); + setLanguage(Settings.data.general.language); } else { - Logger.d("I18n", `No user-defined language, using system detected: "${root.systemDetectedLangCode}"`) - setLanguage(root.systemDetectedLangCode, root.fullLocaleCode) + Logger.d("I18n", `No user-defined language, using system detected: "${root.systemDetectedLangCode}"`); + setLanguage(root.systemDetectedLangCode, root.fullLocaleCode); } } // ------------------------------------------- function setLanguage(newLangCode, fullLocale) { if (typeof fullLocale === "undefined") { - fullLocale = newLangCode + fullLocale = newLangCode; } if (newLangCode !== langCode && availableLanguages.includes(newLangCode)) { - langCode = newLangCode - fullLocaleCode = fullLocale - locale = Qt.locale(fullLocale) - Logger.i("I18n", `Language set to "${langCode}" with locale "${fullLocale}"`) - languageChanged(langCode) - loadTranslations() + langCode = newLangCode; + fullLocaleCode = fullLocale; + locale = Qt.locale(fullLocale); + Logger.i("I18n", `Language set to "${langCode}" with locale "${fullLocale}"`); + languageChanged(langCode); + loadTranslations(); } else if (!availableLanguages.includes(newLangCode)) { - Logger.w("I18n", `Language "${newLangCode}" is not available`) + Logger.w("I18n", `Language "${newLangCode}" is not available`); } } // ------------------------------------------- function loadTranslations() { if (langCode === "") - return - - const filePath = `file://${Quickshell.shellDir}/Assets/Translations/${langCode}.json` - fileView.path = filePath - isLoaded = false - Logger.d("I18n", `Loading translations: ${langCode}`) + return; + const filePath = `file://${Quickshell.shellDir}/Assets/Translations/${langCode}.json`; + fileView.path = filePath; + isLoaded = false; + Logger.d("I18n", `Loading translations: ${langCode}`); // Only load fallback translations if we are not using english and english is available if (langCode !== "en" && availableLanguages.includes("en")) { - fallbackFileView.path = `file://${Quickshell.shellDir}/Assets/Translations/en.json` + fallbackFileView.path = `file://${Quickshell.shellDir}/Assets/Translations/en.json`; } } @@ -239,133 +238,133 @@ Singleton { // Check if a translation exists function hasTranslation(key) { if (!isLoaded) - return false + return false; - const keys = key.split(".") - var value = translations + const keys = key.split("."); + var value = translations; for (var i = 0; i < keys.length; i++) { if (value && typeof value === "object" && keys[i] in value) { - value = value[keys[i]] + value = value[keys[i]]; } else { - return false + return false; } } - return typeof value === "string" + return typeof value === "string"; } // ------------------------------------------- // Get all translation keys (useful for debugging) function getAllKeys(obj, prefix) { if (typeof obj === "undefined") - obj = translations + obj = translations; if (typeof prefix === "undefined") - prefix = "" + prefix = ""; - var keys = [] + var keys = []; for (var key in (obj || {})) { - const value = obj[key] - const fullKey = prefix ? `${prefix}.${key}` : key + const value = obj[key]; + const fullKey = prefix ? `${prefix}.${key}` : key; if (typeof value === "object" && value !== null) { - keys = keys.concat(getAllKeys(value, fullKey)) + keys = keys.concat(getAllKeys(value, fullKey)); } else if (typeof value === "string") { - keys.push(fullKey) + keys.push(fullKey); } } - return keys + return keys; } // ------------------------------------------- // Reload translations (useful for development) function reload() { - Logger.d("I18n", "Reloading translations") - loadTranslations() + Logger.d("I18n", "Reloading translations"); + loadTranslations(); } // ------------------------------------------- // Main translation function function tr(key, interpolations) { if (typeof interpolations === "undefined") - interpolations = {} + interpolations = {}; if (!isLoaded) { //Logger.d("I18n", "Translations not loaded yet") - return key + return key; } // Navigate nested keys (e.g., "menu.file.open") - const keys = key.split(".") + const keys = key.split("."); // Look-up translation in the active language - var value = translations - var notFound = false + var value = translations; + var notFound = false; for (var i = 0; i < keys.length; i++) { if (value && typeof value === "object" && keys[i] in value) { - value = value[keys[i]] + value = value[keys[i]]; } else { - Logger.d("I18n", `Translation key "${key}" not found at part "${keys[i]}"`) - Logger.d("I18n", `Available keys: ${Object.keys(value || {}).join(", ")}`) - notFound = true - break + Logger.d("I18n", `Translation key "${key}" not found at part "${keys[i]}"`); + Logger.d("I18n", `Available keys: ${Object.keys(value || {}).join(", ")}`); + notFound = true; + break; } } // Fallback to english if not found if (notFound && availableLanguages.includes("en") && langCode !== "en") { - value = fallbackTranslations + value = fallbackTranslations; for (var i = 0; i < keys.length; i++) { if (value && typeof value === "object" && keys[i] in value) { - value = value[keys[i]] + value = value[keys[i]]; } else { // Indicate this key does not even exists in the english fallback - return `## ${key} ##` + return `## ${key} ##`; } } // Make untranslated string easy to spot - value = `${value}` + value = `${value}`; } else if (notFound) { // No fallback available - return `## ${key} ##` + return `## ${key} ##`; } if (typeof value !== "string") { - Logger.d("I18n", `Translation key "${key}" is not a string`) - return key + Logger.d("I18n", `Translation key "${key}" is not a string`); + return key; } // Handle interpolations (e.g., "Hello {name}!") - var result = value + var result = value; for (var placeholder in interpolations) { - const regex = new RegExp(`\\{${placeholder}\\}`, 'g') - result = result.replace(regex, interpolations[placeholder]) + const regex = new RegExp(`\\{${placeholder}\\}`, 'g'); + result = result.replace(regex, interpolations[placeholder]); } - return result + return result; } // ------------------------------------------- // Plural translation function function trp(key, count, defaultSingular, defaultPlural, interpolations) { if (typeof defaultSingular === "undefined") - defaultSingular = "" + defaultSingular = ""; if (typeof defaultPlural === "undefined") - defaultPlural = "" + defaultPlural = ""; if (typeof interpolations === "undefined") - interpolations = {} + interpolations = {}; - const pluralKey = count === 1 ? key : `${key}_plural` - const defaultValue = count === 1 ? defaultSingular : defaultPlural + const pluralKey = count === 1 ? key : `${key}_plural`; + const defaultValue = count === 1 ? defaultSingular : defaultPlural; // Merge interpolations with count (QML doesn't support spread operator) var finalInterpolations = { "count": count - } + }; for (var prop in interpolations) { - finalInterpolations[prop] = interpolations[prop] + finalInterpolations[prop] = interpolations[prop]; } - return tr(pluralKey, finalInterpolations) + return tr(pluralKey, finalInterpolations); } } diff --git a/Commons/Icons.qml b/Commons/Icons.qml index acd7e1b7..46d75ab2 100644 --- a/Commons/Icons.qml +++ b/Commons/Icons.qml @@ -26,15 +26,15 @@ Singleton { signal fontReloaded Component.onCompleted: { - Logger.i("Icons", "Service started") - loadFontWithCacheBusting() + Logger.i("Icons", "Service started"); + loadFontWithCacheBusting(); } Connections { target: Quickshell function onReloadCompleted() { - Logger.d("Icons", "Quickshell reload completed - forcing font reload") - reloadFont() + Logger.d("Icons", "Quickshell reload completed - forcing font reload"); + reloadFont(); } } @@ -42,20 +42,20 @@ Singleton { function get(iconName) { // Check in aliases first if (aliases[iconName] !== undefined) { - iconName = aliases[iconName] + iconName = aliases[iconName]; } // Find the appropriate codepoint - return icons[iconName] + return icons[iconName]; } function loadFontWithCacheBusting() { - Logger.d("Icons", "Loading font with cache busting") + Logger.d("Icons", "Loading font with cache busting"); // Destroy old loader first if (currentFontLoader) { - currentFontLoader.destroy() - currentFontLoader = null + currentFontLoader.destroy(); + currentFontLoader = null; } // Create new loader with cache-busting URL @@ -64,22 +64,22 @@ Singleton { FontLoader { source: "${cacheBustingPath}" } - `, root, "dynamicFontLoader_" + fontVersion) + `, root, "dynamicFontLoader_" + fontVersion); // Connect to the new loader's status changes currentFontLoader.statusChanged.connect(function () { if (currentFontLoader.status === FontLoader.Ready) { - Logger.d("Icons", "Font loaded successfully:", currentFontLoader.name, "(version " + fontVersion + ")") - fontReloaded() + Logger.d("Icons", "Font loaded successfully:", currentFontLoader.name, "(version " + fontVersion + ")"); + fontReloaded(); } else if (currentFontLoader.status === FontLoader.Error) { - Logger.e("Icons", "Font failed to load (version " + fontVersion + ")") + Logger.e("Icons", "Font failed to load (version " + fontVersion + ")"); } - }) + }); } function reloadFont() { - Logger.d("Icons", "Forcing font reload...") - fontVersion++ - loadFontWithCacheBusting() + Logger.d("Icons", "Forcing font reload..."); + fontVersion++; + loadFontWithCacheBusting(); } } diff --git a/Commons/IconsTabler.qml b/Commons/IconsTabler.qml index 2db54ae7..7a0b5e80 100644 --- a/Commons/IconsTabler.qml +++ b/Commons/IconsTabler.qml @@ -310,8 +310,8 @@ Singleton { "align-left": "\u{ea09}", "align-left-2": "\u{ff00}", "align-right": "\u{ea0a}", - "alpha"//"align-right-2": "\u{feff}", - : "\u{f543}", + //"align-right-2": "\u{feff}", + "alpha": "\u{f543}", "alphabet-arabic": "\u{ff2f}", "alphabet-bangla": "\u{ff2e}", "alphabet-cyrillic": "\u{f1df}", @@ -3143,8 +3143,8 @@ Singleton { "friends": "\u{eab0}", "friends-off": "\u{f136}", "frustum": "\u{fa9f}", - "frustum-plus"//"frustum-off": "\u{fa9d}", - : "\u{fa9e}", + //"frustum-off": "\u{fa9d}", + "frustum-plus": "\u{fa9e}", "function": "\u{f225}", "function-filled": "\u{fc2b}", "function-off": "\u{f3f0}", @@ -3403,13 +3403,13 @@ Singleton { "hexagon-letter-x": "\u{f479}", "hexagon-letter-x-filled": "\u{fe30}", "hexagon-letter-y": "\u{f47a}", - "hexagon-letter-z"//"hexagon-letter-y-filled": "\u{fe2f}", - : "\u{f47b}", - "hexagon-minus"//"hexagon-letter-z-filled": "\u{fe2e}", - : "\u{fc8f}", + //"hexagon-letter-y-filled": "\u{fe2f}", + "hexagon-letter-z": "\u{f47b}", + //"hexagon-letter-z-filled": "\u{fe2e}", + "hexagon-minus": "\u{fc8f}", "hexagon-minus-2": "\u{fc8e}", - "hexagon-number-0"//"hexagon-minus-filled": "\u{fe2d}", - : "\u{f459}", + //"hexagon-minus-filled": "\u{fe2d}", + "hexagon-number-0": "\u{f459}", "hexagon-number-0-filled": "\u{f74c}", "hexagon-number-1": "\u{f45a}", "hexagon-number-1-filled": "\u{f74d}", @@ -3432,8 +3432,8 @@ Singleton { "hexagon-off": "\u{ee9c}", "hexagon-plus": "\u{fc45}", "hexagon-plus-2": "\u{fc90}", - "hexagonal-prism"//"hexagon-plus-filled": "\u{fe2c}", - : "\u{faa5}", + //"hexagon-plus-filled": "\u{fe2c}", + "hexagonal-prism": "\u{faa5}", "hexagonal-prism-off": "\u{faa3}", "hexagonal-prism-plus": "\u{faa4}", "hexagonal-pyramid": "\u{faa8}", @@ -3463,8 +3463,8 @@ Singleton { "home-eco": "\u{f351}", "home-edit": "\u{f352}", "home-exclamation": "\u{f33c}", - "home-hand"//"home-filled": "\u{fe2b}", - : "\u{f504}", + //"home-filled": "\u{fe2b}", + "home-hand": "\u{f504}", "home-heart": "\u{f353}", "home-infinity": "\u{f505}", "home-link": "\u{f354}", @@ -3582,8 +3582,8 @@ Singleton { "ironing-2-filled": "\u{1006e}", "ironing-3": "\u{f2f6}", "ironing-3-filled": "\u{1006d}", - "ironing-off"//"ironing-filled": "\u{fe2a}", - : "\u{f2f7}", + //"ironing-filled": "\u{fe2a}", + "ironing-off": "\u{f2f7}", "ironing-steam": "\u{f2f9}", "ironing-steam-filled": "\u{1006c}", "ironing-steam-off": "\u{f2f8}", @@ -3593,8 +3593,8 @@ Singleton { "italic": "\u{eb93}", "jacket": "\u{f661}", "jetpack": "\u{f581}", - "jewish-star"//"jetpack-filled": "\u{fe29}", - : "\u{f3ff}", + //"jetpack-filled": "\u{fe29}", + "jewish-star": "\u{f3ff}", "jewish-star-filled": "\u{f67e}", "join-bevel": "\u{ff4c}", "join-round": "\u{ff4b}", @@ -3608,8 +3608,8 @@ Singleton { "kering": "\u{efb8}", "kerning": "\u{efb8}", "key": "\u{eac7}", - "key-off"//"key-filled": "\u{fe28}", - : "\u{f14b}", + //"key-filled": "\u{fe28}", + "key-off": "\u{f14b}", "keyboard": "\u{ebd6}", "keyboard-filled": "\u{100a2}", "keyboard-hide": "\u{ec7e}", @@ -3665,20 +3665,20 @@ Singleton { "layers-union": "\u{eacb}", "layout": "\u{eadb}", "layout-2": "\u{eacc}", - "layout-align-left"//"layout-2-filled": "\u{fe27}", - // "layout-align-bottom": "\u{eacd}", + //"layout-2-filled": "\u{fe27}", + //"layout-align-bottom": "\u{eacd}", //"layout-align-bottom-filled": "\u{fe26}", - // "layout-align-center": "\u{eace}", + //"layout-align-center": "\u{eace}", //"layout-align-center-filled": "\u{fe25}", - : "\u{eacf}", - "layout-align-middle"// "layout-align-left-filled": "\u{fe24}", - : "\u{ead0}", - "layout-align-right"//"layout-align-middle-filled": "\u{fe23}", - : "\u{ead1}", - "layout-align-top"//"layout-align-right-filled": "\u{fe22}", - : "\u{ead2}", - "layout-board"//"layout-align-top-filled": "\u{fe21}", - : "\u{ef95}", + "layout-align-left": "\u{eacf}", + //"layout-align-left-filled": "\u{fe24}", + "layout-align-middle": "\u{ead0}", + //"layout-align-middle-filled": "\u{fe23}", + "layout-align-right": "\u{ead1}", + //"layout-align-right-filled": "\u{fe22}", + "layout-align-top": "\u{ead2}", + //"layout-align-top-filled": "\u{fe21}", + "layout-board": "\u{ef95}", "layout-board-filled": "\u{10182}", "layout-board-split": "\u{ef94}", "layout-board-split-filled": "\u{10183}", @@ -3690,8 +3690,8 @@ Singleton { "layout-bottombar-filled": "\u{fc37}", "layout-bottombar-inactive": "\u{fd45}", "layout-cards": "\u{ec13}", - "layout-collage"// "layout-cards-filled": "\u{fe20}", - : "\u{f389}", + //"layout-cards-filled": "\u{fe20}", + "layout-collage": "\u{f389}", "layout-columns": "\u{ead4}", "layout-dashboard": "\u{f02c}", "layout-dashboard-filled": "\u{fe1f}", @@ -4172,14 +4172,14 @@ Singleton { "microphone": "\u{eaf0}", "microphone-2": "\u{ef2c}", "microphone-2-off": "\u{f40d}", - "microphone-off"//"microphone-filled": "\u{fe0f}", - : "\u{ed16}", + //"microphone-filled": "\u{fe0f}", + "microphone-off": "\u{ed16}", "microscope": "\u{ef64}", "microscope-filled": "\u{10166}", "microscope-off": "\u{f40e}", "microwave": "\u{f248}", - "microwave-off"//"microwave-filled": "\u{fe0e}", - : "\u{f264}", + //"microwave-filled": "\u{fe0e}", + "microwave-off": "\u{f264}", "military-award": "\u{f079}", "military-rank": "\u{efcf}", "military-rank-filled": "\u{ff5e}", @@ -4413,18 +4413,18 @@ Singleton { "number-4-small": "\u{fcf9}", "number-40-small": "\u{fffa}", "number-41-small": "\u{fff9}", - "number-5"//"number-42-small": "\u{fff8}", - // "number-43-small": "\u{fff7}", - // "number-44-small": "\u{fff6}", - // "number-45-small": "\u{fff5}", - // "number-46-small": "\u{fff4}", - // "number-47-small": "\u{fff3}", - // "number-48-small": "\u{fff2}", - // "number-49-small": "\u{fff1}", - : "\u{edf5}", + //"number-42-small": "\u{fff8}", + //"number-43-small": "\u{fff7}", + //"number-44-small": "\u{fff6}", + //"number-45-small": "\u{fff5}", + //"number-46-small": "\u{fff4}", + //"number-47-small": "\u{fff3}", + //"number-48-small": "\u{fff2}", + //"number-49-small": "\u{fff1}", + "number-5": "\u{edf5}", "number-5-small": "\u{fcfa}", - "number-51-small"// "number-50-small": "\u{fff0}", - : "\u{ffef}", + //"number-50-small": "\u{fff0}", + "number-51-small": "\u{ffef}", "number-52-small": "\u{ffee}", "number-53-small": "\u{ffed}", "number-54-small": "\u{ffec}", @@ -4864,11 +4864,11 @@ Singleton { "quote": "\u{efbe}", "quote-filled": "\u{1009c}", "quote-off": "\u{f188}", - "radar"//"quotes": "\u{fb1e}", - : "\u{f017}", + //"quotes": "\u{fb1e}", + "radar": "\u{f017}", "radar-2": "\u{f016}", - "radar-off"//"radar-filled": "\u{fe0d}", - : "\u{f41f}", + //"radar-filled": "\u{fe0d}", + "radar-off": "\u{f41f}", "radio": "\u{ef2d}", "radio-off": "\u{f420}", "radioactive": "\u{ecc0}", @@ -4928,12 +4928,12 @@ Singleton { "regex-off": "\u{f421}", "registered": "\u{eb14}", "relation-many-to-many": "\u{ed7f}", - "relation-one-to-many"//"relation-many-to-many-filled": "\u{fe0c}", - : "\u{ed80}", - "relation-one-to-one"//"relation-one-to-many-filled": "\u{fe0b}", - : "\u{ed81}", - "reload"//"relation-one-to-one-filled": "\u{fe0a}", - : "\u{f3ae}", + //"relation-many-to-many-filled": "\u{fe0c}", + "relation-one-to-many": "\u{ed80}", + //"relation-one-to-many-filled": "\u{fe0b}", + "relation-one-to-one": "\u{ed81}", + //"relation-one-to-one-filled": "\u{fe0a}", + "reload": "\u{f3ae}", "reorder": "\u{fc15}", "repeat": "\u{eb72}", "repeat-off": "\u{f18e}", @@ -5085,8 +5085,8 @@ Singleton { "search": "\u{eb1c}", "search-off": "\u{f19c}", "section": "\u{eed5}", - "section-sign"//"section-filled": "\u{fe09}", - : "\u{f019}", + //"section-filled": "\u{fe09}", + "section-sign": "\u{f019}", "seeding": "\u{ed51}", "seeding-filled": "\u{10006}", "seeding-off": "\u{f19d}", @@ -5294,8 +5294,8 @@ Singleton { "sort-z-a": "\u{f550}", "sos": "\u{f24a}", "soup": "\u{ef2e}", - "soup-off"//"soup-filled": "\u{fe08}", - : "\u{f42d}", + //"soup-filled": "\u{fe08}", + "soup-off": "\u{f42d}", "source-code": "\u{f4a2}", "space": "\u{ec0c}", "space-off": "\u{f1aa}", @@ -5388,22 +5388,22 @@ Singleton { "square-half": "\u{effb}", "square-key": "\u{f638}", "square-letter-a": "\u{f47c}", - "square-letter-b"//"square-letter-a-filled": "\u{fe07}", - : "\u{f47d}", - "square-letter-c"//"square-letter-b-filled": "\u{fe06}", - : "\u{f47e}", - "square-letter-d"//"square-letter-c-filled": "\u{fe05}", - : "\u{f47f}", - "square-letter-e"//"square-letter-d-filled": "\u{fe04}", - : "\u{f480}", - "square-letter-f"//"square-letter-e-filled": "\u{fe03}", - : "\u{f481}", - "square-letter-g"//"square-letter-f-filled": "\u{fe02}", - : "\u{f482}", - "square-letter-h"//"square-letter-g-filled": "\u{fe01}", - : "\u{f483}", - "square-letter-i"//"square-letter-h-filled": "\u{fe00}", - : "\u{f484}", + //"square-letter-a-filled": "\u{fe07}", + "square-letter-b": "\u{f47d}", + //"square-letter-b-filled": "\u{fe06}", + "square-letter-c": "\u{f47e}", + //"square-letter-c-filled": "\u{fe05}", + "square-letter-d": "\u{f47f}", + //"square-letter-d-filled": "\u{fe04}", + "square-letter-e": "\u{f480}", + //"square-letter-e-filled": "\u{fe03}", + "square-letter-f": "\u{f481}", + //"square-letter-f-filled": "\u{fe02}", + "square-letter-g": "\u{f482}", + //"square-letter-g-filled": "\u{fe01}", + "square-letter-h": "\u{f483}", + //"square-letter-h-filled": "\u{fe00}", + "square-letter-i": "\u{f484}", "square-letter-i-filled": "\u{fdff}", "square-letter-j": "\u{f485}", "square-letter-j-filled": "\u{fdfe}", diff --git a/Commons/Logger.qml b/Commons/Logger.qml index 5c18b90b..4fb4b325 100644 --- a/Commons/Logger.qml +++ b/Commons/Logger.qml @@ -7,63 +7,63 @@ Singleton { id: root function _formatMessage(...args) { - var t = Time.getFormattedTimestamp() + var t = Time.getFormattedTimestamp(); if (args.length > 1) { - const maxLength = 14 - var module = args.shift().substring(0, maxLength).padStart(maxLength, " ") - return `\x1b[36m[${t}]\x1b[0m \x1b[35m${module}\x1b[0m ` + args.join(" ") + const maxLength = 14; + var module = args.shift().substring(0, maxLength).padStart(maxLength, " "); + return `\x1b[36m[${t}]\x1b[0m \x1b[35m${module}\x1b[0m ` + args.join(" "); } else { - return `[\x1b[36m[${t}]\x1b[0m ` + args.join(" ") + return `[\x1b[36m[${t}]\x1b[0m ` + args.join(" "); } } function _getStackTrace() { try { - throw new Error("Stack trace") + throw new Error("Stack trace"); } catch (e) { - return e.stack + return e.stack; } } // Debug log (only when Settings.isDebug is true) function d(...args) { - if (Settings && Settings.isDebug) { - var msg = _formatMessage(...args) - console.debug(msg) + if (Settings?.isDebug) { + var msg = _formatMessage(...args); + console.debug(msg); } } // Info log (always visible) function i(...args) { - var msg = _formatMessage(...args) - console.info(msg) + var msg = _formatMessage(...args); + console.info(msg); } // Warning log (always visible) function w(...args) { - var msg = _formatMessage(...args) - console.warn(msg) + var msg = _formatMessage(...args); + console.warn(msg); } // Error log (always visible) function e(...args) { - var msg = _formatMessage(...args) - console.error(msg) + var msg = _formatMessage(...args); + console.error(msg); } function callStack() { - var stack = _getStackTrace() - Logger.i("Debug", "--------------------------") - Logger.i("Debug", "Current call stack") + var stack = _getStackTrace(); + Logger.i("Debug", "--------------------------"); + Logger.i("Debug", "Current call stack"); // Split the stack into lines and log each one - var stackLines = stack.split('\n') + var stackLines = stack.split('\n'); for (var i = 0; i < stackLines.length; i++) { - var line = stackLines[i].trim() // Remove leading/trailing whitespace + var line = stackLines[i].trim(); // Remove leading/trailing whitespace if (line.length > 0) { // Only log non-empty lines - Logger.i("Debug", `- ${line}`) + Logger.i("Debug", `- ${line}`); } } - Logger.i("Debug", "--------------------------") + Logger.i("Debug", "--------------------------"); } } diff --git a/Commons/Settings.qml b/Commons/Settings.qml index efe3ef5a..4d22d191 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -3,9 +3,9 @@ pragma Singleton import QtQuick import Quickshell import Quickshell.Io +import "../Helpers/QtObj2JS.js" as QtObj2JS import qs.Commons import qs.Services.UI -import "../Helpers/QtObj2JS.js" as QtObj2JS Singleton { id: root @@ -42,30 +42,30 @@ Singleton { // Ensure directories exist before FileView tries to read files Component.onCompleted: { // ensure settings dir exists - Quickshell.execDetached(["mkdir", "-p", configDir]) - Quickshell.execDetached(["mkdir", "-p", cacheDir]) + Quickshell.execDetached(["mkdir", "-p", configDir]); + Quickshell.execDetached(["mkdir", "-p", cacheDir]); - Quickshell.execDetached(["mkdir", "-p", cacheDirImagesWallpapers]) - Quickshell.execDetached(["mkdir", "-p", cacheDirImagesNotifications]) + Quickshell.execDetached(["mkdir", "-p", cacheDirImagesWallpapers]); + Quickshell.execDetached(["mkdir", "-p", cacheDirImagesNotifications]); // Mark directories as created and trigger file loading - directoriesCreated = true + directoriesCreated = true; // This should only be activated once when the settings structure has changed // Then it should be commented out again, regular users don't need to generate // default settings on every start if (isDebug) { - generateDefaultSettings() + generateDefaultSettings(); } // Patch-in the local default, resolved to user's home - adapter.general.avatarImage = defaultAvatar - adapter.screenRecorder.directory = defaultVideosDirectory - adapter.wallpaper.directory = defaultWallpapersDirectory - adapter.wallpaper.defaultWallpaper = Quickshell.shellDir + "/Assets/Wallpaper/noctalia.png" + adapter.general.avatarImage = defaultAvatar; + adapter.screenRecorder.directory = defaultVideosDirectory; + adapter.wallpaper.directory = defaultWallpapersDirectory; + adapter.wallpaper.defaultWallpaper = Quickshell.shellDir + "/Assets/Wallpaper/noctalia.png"; // Set the adapter to the settingsFileView to trigger the real settings load - settingsFileView.adapter = adapter + settingsFileView.adapter = adapter; } // Don't write settings to disk immediately @@ -75,7 +75,7 @@ Singleton { running: false interval: 1000 onTriggered: { - root.saveImmediate() + root.saveImmediate(); } } @@ -90,31 +90,31 @@ Singleton { // Trigger initial load when path changes from empty to actual path onPathChanged: { if (path !== undefined) { - reload() + reload(); } } onLoaded: function () { if (!isLoaded) { - Logger.i("Settings", "Settings loaded") + Logger.i("Settings", "Settings loaded"); - upgradeSettingsData() - validateMonitorConfigurations() - isLoaded = true + upgradeSettingsData(); + validateMonitorConfigurations(); + isLoaded = true; // Emit the signal - root.settingsLoaded() + root.settingsLoaded(); // Finally, update our local settings version - adapter.settingsVersion = settingsVersion + adapter.settingsVersion = settingsVersion; } } onLoadFailed: function (error) { if (error.toString().includes("No such file") || error === 2) { // File doesn't exist, create it with default values - writeAdapter() + writeAdapter(); // Also write to fallback if set if (Quickshell.env("NOCTALIA_SETTINGS_FALLBACK")) { - settingsFallbackFileView.writeAdapter() + settingsFallbackFileView.writeAdapter(); } } } @@ -156,33 +156,48 @@ Singleton { // Widget configuration for modular bar system property JsonObject widgets widgets: JsonObject { - property list left: [{ + property list left: [ + { "id": "ControlCenter" - }, { + }, + { "id": "SystemMonitor" - }, { + }, + { "id": "ActiveWindow" - }, { + }, + { "id": "MediaMini" - }] - property list center: [{ + } + ] + property list center: [ + { "id": "Workspace" - }] - property list right: [{ + } + ] + property list right: [ + { "id": "ScreenRecorder" - }, { + }, + { "id": "Tray" - }, { + }, + { "id": "NotificationHistory" - }, { + }, + { "id": "Battery" - }, { + }, + { "id": "Volume" - }, { + }, + { "id": "Brightness" - }, { + }, + { "id": "Clock" - }] + } + ] } } @@ -294,41 +309,57 @@ Singleton { property string position: "close_to_bar_button" property JsonObject shortcuts shortcuts: JsonObject { - property list left: [{ + property list left: [ + { "id": "WiFi" - }, { + }, + { "id": "Bluetooth" - }, { + }, + { "id": "ScreenRecorder" - }, { + }, + { "id": "WallpaperSelector" - }] - property list right: [{ + } + ] + property list right: [ + { "id": "Notifications" - }, { + }, + { "id": "PowerProfile" - }, { + }, + { "id": "KeepAwake" - }, { + }, + { "id": "NightLight" - }] + } + ] } - property list cards: [{ + property list cards: [ + { "id": "profile-card", "enabled": true - }, { + }, + { "id": "shortcuts-card", "enabled": true - }, { + }, + { "id": "audio-card", "enabled": true - }, { + }, + { "id": "weather-card", "enabled": true - }, { + }, + { "id": "media-sysmon-card", "enabled": true - }] + } + ] } // system monitor @@ -371,25 +402,32 @@ Singleton { property int countdownDuration: 10000 property string position: "center" property bool showHeader: true - property list powerOptions: [{ + property list powerOptions: [ + { "action": "lock", "enabled": true - }, { + }, + { "action": "suspend", "enabled": true - }, { + }, + { "action": "hibernate", "enabled": true - }, { + }, + { "action": "reboot", "enabled": true - }, { + }, + { "action": "logout", "enabled": true - }, { + }, + { "action": "shutdown", "enabled": true - }] + } + ] } // notifications @@ -493,81 +531,81 @@ Singleton { // Function to preprocess paths by expanding "~" to user's home directory function preprocessPath(path) { if (typeof path !== "string" || path === "") { - return path + return path; } // Expand "~" to user's home directory if (path.startsWith("~/")) { - return Quickshell.env("HOME") + path.substring(1) + return Quickshell.env("HOME") + path.substring(1); } else if (path === "~") { - return Quickshell.env("HOME") + return Quickshell.env("HOME"); } - return path + return path; } // ----------------------------------------------------- // Public function to trigger immediate settings saving function saveImmediate() { - settingsFileView.writeAdapter() + settingsFileView.writeAdapter(); // Write to fallback location if set if (Quickshell.env("NOCTALIA_SETTINGS_FALLBACK")) { - settingsFallbackFileView.writeAdapter() + settingsFallbackFileView.writeAdapter(); } - root.settingsSaved() // Emit signal after saving + root.settingsSaved(); // Emit signal after saving } // ----------------------------------------------------- // Generate default settings at the root of the repo function generateDefaultSettings() { try { - Logger.d("Settings", "Generating settings-default.json") + Logger.d("Settings", "Generating settings-default.json"); // Prepare a clean JSON - var plainAdapter = QtObj2JS.qtObjectToPlainObject(adapter) - var jsonData = JSON.stringify(plainAdapter, null, 2) + var plainAdapter = QtObj2JS.qtObjectToPlainObject(adapter); + var jsonData = JSON.stringify(plainAdapter, null, 2); - var defaultPath = Quickshell.shellDir + "/Assets/settings-default.json" + var defaultPath = Quickshell.shellDir + "/Assets/settings-default.json"; // Encode transfer it has base64 to avoid any escaping issue - var base64Data = Qt.btoa(jsonData) - Quickshell.execDetached(["sh", "-c", `echo "${base64Data}" | base64 -d > "${defaultPath}"`]) + var base64Data = Qt.btoa(jsonData); + Quickshell.execDetached(["sh", "-c", `echo "${base64Data}" | base64 -d > "${defaultPath}"`]); } catch (error) { - Logger.e("Settings", "Failed to generate default settings file: " + error) + Logger.e("Settings", "Failed to generate default settings file: " + error); } } // ----------------------------------------------------- // Function to validate monitor configurations function validateMonitorConfigurations() { - var availableScreenNames = [] + var availableScreenNames = []; for (var i = 0; i < Quickshell.screens.length; i++) { - availableScreenNames.push(Quickshell.screens[i].name) + availableScreenNames.push(Quickshell.screens[i].name); } - Logger.d("Settings", "Available monitors: [" + availableScreenNames.join(", ") + "]") - Logger.d("Settings", "Configured bar monitors: [" + adapter.bar.monitors.join(", ") + "]") + Logger.d("Settings", "Available monitors: [" + availableScreenNames.join(", ") + "]"); + Logger.d("Settings", "Configured bar monitors: [" + adapter.bar.monitors.join(", ") + "]"); // Check bar monitors if (adapter.bar.monitors.length > 0) { - var hasValidBarMonitor = false + var hasValidBarMonitor = false; for (var j = 0; j < adapter.bar.monitors.length; j++) { if (availableScreenNames.includes(adapter.bar.monitors[j])) { - hasValidBarMonitor = true - break + hasValidBarMonitor = true; + break; } } if (!hasValidBarMonitor) { - Logger.w("Settings", "No configured bar monitors found on system, clearing bar monitor list to show on all screens") - adapter.bar.monitors = [] - } else { + Logger.w("Settings", "No configured bar monitors found on system, clearing bar monitor list to show on all screens"); + adapter.bar.monitors = []; + } else //Logger.i("Settings", "Found valid bar monitors, keeping configuration") - } - } else { + {} + } else //Logger.i("Settings", "Bar monitor list is empty, will show on all available screens") - } + {} } // ----------------------------------------------------- @@ -576,50 +614,50 @@ Singleton { function upgradeSettingsData() { // Wait for BarWidgetRegistry to be ready if (!BarWidgetRegistry.widgets || Object.keys(BarWidgetRegistry.widgets).length === 0) { - Logger.w("Settings", "BarWidgetRegistry not ready, deferring upgrade") - Qt.callLater(upgradeSettingsData) - return + Logger.w("Settings", "BarWidgetRegistry not ready, deferring upgrade"); + Qt.callLater(upgradeSettingsData); + return; } - const sections = ["left", "center", "right"] + const sections = ["left", "center", "right"]; // ----------------- // 1st. convert old widget id to new id for (var s = 0; s < sections.length; s++) { - const sectionName = sections[s] + const sectionName = sections[s]; for (var i = 0; i < adapter.bar.widgets[sectionName].length; i++) { - var widget = adapter.bar.widgets[sectionName][i] + var widget = adapter.bar.widgets[sectionName][i]; switch (widget.id) { case "DarkModeToggle": - widget.id = "DarkMode" - break + widget.id = "DarkMode"; + break; case "PowerToggle": - widget.id = "SessionMenu" - break + widget.id = "SessionMenu"; + break; case "ScreenRecorderIndicator": - widget.id = "ScreenRecorder" - break + widget.id = "ScreenRecorder"; + break; case "SidePanelToggle": - widget.id = "ControlCenter" - break + widget.id = "ControlCenter"; + break; } } } // ----------------- // 2nd. remove any non existing widget type - var removedWidget = false + var removedWidget = false; for (var s = 0; s < sections.length; s++) { - const sectionName = sections[s] - const widgets = adapter.bar.widgets[sectionName] + const sectionName = sections[s]; + const widgets = adapter.bar.widgets[sectionName]; // Iterate backward through the widgets array, so it does not break when removing a widget for (var i = widgets.length - 1; i >= 0; i--) { - var widget = widgets[i] + var widget = widgets[i]; if (!BarWidgetRegistry.hasWidget(widget.id)) { - Logger.w(`Settings`, `Deleted invalid widget ${widget.id}`) - widgets.splice(i, 1) - removedWidget = true + Logger.w(`Settings`, `Deleted invalid widget ${widget.id}`); + widgets.splice(i, 1); + removedWidget = true; } } } @@ -627,18 +665,18 @@ Singleton { // ----------------- // 3nd. upgrade widget settings for (var s = 0; s < sections.length; s++) { - const sectionName = sections[s] + const sectionName = sections[s]; for (var i = 0; i < adapter.bar.widgets[sectionName].length; i++) { - var widget = adapter.bar.widgets[sectionName][i] + var widget = adapter.bar.widgets[sectionName][i]; // Check if widget registry supports user settings, if it does not, then there is nothing to do - const reg = BarWidgetRegistry.widgetMetadata[widget.id] + const reg = BarWidgetRegistry.widgetMetadata[widget.id]; if ((reg === undefined) || (reg.allowUserSettings === undefined) || !reg.allowUserSettings) { - continue + continue; } if (upgradeWidget(widget)) { - Logger.d("Settings", `Upgraded ${widget.id} widget:`, JSON.stringify(widget)) + Logger.d("Settings", `Upgraded ${widget.id} widget:`, JSON.stringify(widget)); } } } @@ -647,14 +685,14 @@ Singleton { // 4th. safety check // if a widget was deleted, ensure we still have a control center if (removedWidget) { - var gotControlCenter = false + var gotControlCenter = false; for (var s = 0; s < sections.length; s++) { - const sectionName = sections[s] + const sectionName = sections[s]; for (var i = 0; i < adapter.bar.widgets[sectionName].length; i++) { - var widget = adapter.bar.widgets[sectionName][i] + var widget = adapter.bar.widgets[sectionName][i]; if (widget.id === "ControlCenter") { - gotControlCenter = true - break + gotControlCenter = true; + break; } } } @@ -663,8 +701,8 @@ Singleton { //const obj = JSON.parse('{"id": "ControlCenter"}'); adapter.bar.widgets["right"].push(({ "id": "ControlCenter" - })) - Logger.w("Settings", "Added a ControlCenter widget to the right section") + })); + Logger.w("Settings", "Added a ControlCenter widget to the right section"); } } @@ -674,31 +712,31 @@ Singleton { if (adapter.settingsVersion < 21) { // Read raw JSON file to access properties not in adapter schema try { - var rawJson = settingsFileView.text() + var rawJson = settingsFileView.text(); if (rawJson) { - var parsed = JSON.parse(rawJson) - var anyDiscordEnabled = false + var parsed = JSON.parse(rawJson); + var anyDiscordEnabled = false; // Check if any Discord client was enabled - const discordClients = ["discord_vesktop", "discord_webcord", "discord_armcord", "discord_equibop", "discord_lightcord", "discord_dorion", "discord_vencord"] + const discordClients = ["discord_vesktop", "discord_webcord", "discord_armcord", "discord_equibop", "discord_lightcord", "discord_dorion", "discord_vencord"]; if (parsed.templates) { for (var i = 0; i < discordClients.length; i++) { if (parsed.templates[discordClients[i]]) { - anyDiscordEnabled = true - break + anyDiscordEnabled = true; + break; } } } // Set unified discord property - adapter.templates.discord = anyDiscordEnabled + adapter.templates.discord = anyDiscordEnabled; - Logger.i("Settings", "Migrated Discord templates to unified 'discord' property (enabled:", anyDiscordEnabled + ")") + Logger.i("Settings", "Migrated Discord templates to unified 'discord' property (enabled:", anyDiscordEnabled + ")"); } } catch (error) { - Logger.w("Settings", "Failed to read raw JSON for Discord migration:", error) + Logger.w("Settings", "Failed to read raw JSON for Discord migration:", error); } } @@ -708,20 +746,20 @@ Singleton { if (adapter.settingsVersion < 22) { // Read raw JSON file to access properties not in adapter schema try { - var rawJson = settingsFileView.text() + var rawJson = settingsFileView.text(); if (rawJson) { - var parsed = JSON.parse(rawJson) + var parsed = JSON.parse(rawJson); if (parsed.appLauncher && parsed.appLauncher.backgroundOpacity !== undefined) { - var oldOpacity = parsed.appLauncher.backgroundOpacity + var oldOpacity = parsed.appLauncher.backgroundOpacity; if (adapter.ui) { - adapter.ui.panelBackgroundOpacity = oldOpacity - Logger.i("Settings", "Migrated appLauncher.backgroundOpacity to ui.panelBackgroundOpacity (value:", oldOpacity + ")") + adapter.ui.panelBackgroundOpacity = oldOpacity; + Logger.i("Settings", "Migrated appLauncher.backgroundOpacity to ui.panelBackgroundOpacity (value:", oldOpacity + ")"); } } } } catch (error) { - Logger.w("Settings", "Failed to read raw JSON for migration:", error) + Logger.w("Settings", "Failed to read raw JSON for migration:", error); } } @@ -732,23 +770,23 @@ Singleton { if (adapter.settingsVersion < 23) { // Read raw JSON file to access dimDesktop property try { - var rawJson = settingsFileView.text() + var rawJson = settingsFileView.text(); if (rawJson) { - var parsed = JSON.parse(rawJson) + var parsed = JSON.parse(rawJson); if (parsed.general && parsed.general.dimDesktop === true) { // Check if dimmerOpacity exists in raw JSON (not adapter default) - var dimmerOpacityInJson = parsed.general.dimmerOpacity + var dimmerOpacityInJson = parsed.general.dimmerOpacity; // If dimmerOpacity wasn't explicitly set in JSON or was 0, set it to 0.8 (80% dimming) if (dimmerOpacityInJson === undefined || dimmerOpacityInJson === 0) { - adapter.general.dimmerOpacity = 0.8 - Logger.i("Settings", "Migrated dimDesktop=true: set dimmerOpacity to 0.8 (80% dimming)") + adapter.general.dimmerOpacity = 0.8; + Logger.i("Settings", "Migrated dimDesktop=true: set dimmerOpacity to 0.8 (80% dimming)"); } } } } catch (error) { - Logger.w("Settings", "Failed to read raw JSON for dimDesktop migration:", error) + Logger.w("Settings", "Failed to read raw JSON for dimDesktop migration:", error); } } } @@ -756,35 +794,35 @@ Singleton { // ----------------------------------------------------- function upgradeWidget(widget) { // Backup the widget definition before altering - const widgetBefore = JSON.stringify(widget) + const widgetBefore = JSON.stringify(widget); // Get all existing custom settings keys - const keys = Object.keys(BarWidgetRegistry.widgetMetadata[widget.id]) + const keys = Object.keys(BarWidgetRegistry.widgetMetadata[widget.id]); // Delete deprecated user settings from the wiget for (const k of Object.keys(widget)) { if (k === "id" || k === "allowUserSettings") { - continue + continue; } if (!keys.includes(k)) { - delete widget[k] + delete widget[k]; } } // Inject missing default setting (metaData) from BarWidgetRegistry for (var i = 0; i < keys.length; i++) { - const k = keys[i] + const k = keys[i]; if (k === "id" || k === "allowUserSettings") { - continue + continue; } if (widget[k] === undefined) { - widget[k] = BarWidgetRegistry.widgetMetadata[widget.id][k] + widget[k] = BarWidgetRegistry.widgetMetadata[widget.id][k]; } } // Compare settings, to detect if something has been upgraded - const widgetAfter = JSON.stringify(widget) - return (widgetAfter !== widgetBefore) + const widgetAfter = JSON.stringify(widget); + return (widgetAfter !== widgetBefore); } } diff --git a/Commons/Style.qml b/Commons/Style.qml index b2999d7b..64e4e22b 100644 --- a/Commons/Style.qml +++ b/Commons/Style.qml @@ -7,108 +7,101 @@ import qs.Services.Power Singleton { id: root - - /* - Preset sizes for font, radii, ? - */ - // Font size - property real fontSizeXXS: 8 - property real fontSizeXS: 9 - property real fontSizeS: 10 - property real fontSizeM: 11 - property real fontSizeL: 13 - property real fontSizeXL: 16 - property real fontSizeXXL: 18 - property real fontSizeXXXL: 24 + readonly property real fontSizeXXS: 8 + readonly property real fontSizeXS: 9 + readonly property real fontSizeS: 10 + readonly property real fontSizeM: 11 + readonly property real fontSizeL: 13 + readonly property real fontSizeXL: 16 + readonly property real fontSizeXXL: 18 + readonly property real fontSizeXXXL: 24 // Font weight - property int fontWeightRegular: 400 - property int fontWeightMedium: 500 - property int fontWeightSemiBold: 600 - property int fontWeightBold: 700 + readonly property int fontWeightRegular: 400 + readonly property int fontWeightMedium: 500 + readonly property int fontWeightSemiBold: 600 + readonly property int fontWeightBold: 700 // Radii - property int radiusXXS: Math.round(4 * Settings.data.general.radiusRatio) - property int radiusXS: Math.round(8 * Settings.data.general.radiusRatio) - property int radiusS: Math.round(12 * Settings.data.general.radiusRatio) - property int radiusM: Math.round(16 * Settings.data.general.radiusRatio) - property int radiusL: Math.round(20 * Settings.data.general.radiusRatio) - property int screenRadius: Math.round(20 * Settings.data.general.screenRadiusRatio) + readonly property int radiusXXS: Math.round(4 * Settings.data.general.radiusRatio) + readonly property int radiusXS: Math.round(8 * Settings.data.general.radiusRatio) + readonly property int radiusS: Math.round(12 * Settings.data.general.radiusRatio) + readonly property int radiusM: Math.round(16 * Settings.data.general.radiusRatio) + readonly property int radiusL: Math.round(20 * Settings.data.general.radiusRatio) + readonly property int screenRadius: Math.round(20 * Settings.data.general.screenRadiusRatio) // Border - property int borderS: Math.max(1, Math.round(1 * uiScaleRatio)) - property int borderM: Math.max(1, Math.round(2 * uiScaleRatio)) - property int borderL: Math.max(1, Math.round(3 * uiScaleRatio)) + readonly property int borderS: Math.max(1, Math.round(1 * uiScaleRatio)) + readonly property int borderM: Math.max(1, Math.round(2 * uiScaleRatio)) + readonly property int borderL: Math.max(1, Math.round(3 * uiScaleRatio)) // Margins (for margins and spacing) - property int marginXXS: Math.round(2 * uiScaleRatio) - property int marginXS: Math.round(4 * uiScaleRatio) - property int marginS: Math.round(6 * uiScaleRatio) - property int marginM: Math.round(9 * uiScaleRatio) - property int marginL: Math.round(13 * uiScaleRatio) - property int marginXL: Math.round(18 * uiScaleRatio) + readonly property int marginXXS: Math.round(2 * uiScaleRatio) + readonly property int marginXS: Math.round(4 * uiScaleRatio) + readonly property int marginS: Math.round(6 * uiScaleRatio) + readonly property int marginM: Math.round(9 * uiScaleRatio) + readonly property int marginL: Math.round(13 * uiScaleRatio) + readonly property int marginXL: Math.round(18 * uiScaleRatio) // Opacity - property real opacityNone: 0.0 - property real opacityLight: 0.25 - property real opacityMedium: 0.5 - property real opacityHeavy: 0.75 - property real opacityAlmost: 0.95 - property real opacityFull: 1.0 + readonly property real opacityNone: 0.0 + readonly property real opacityLight: 0.25 + readonly property real opacityMedium: 0.5 + readonly property real opacityHeavy: 0.75 + readonly property real opacityAlmost: 0.95 + readonly property real opacityFull: 1.0 // Shadows - property real shadowOpacity: 0.85 - property real shadowBlur: 1.0 - property int shadowBlurMax: 22 - property real shadowHorizontalOffset: Settings.data.general.shadowOffsetX - property real shadowVerticalOffset: Settings.data.general.shadowOffsetY + readonly property real shadowOpacity: 0.85 + readonly property real shadowBlur: 1.0 + readonly property int shadowBlurMax: 22 + readonly property real shadowHorizontalOffset: Settings.data.general.shadowOffsetX + readonly property real shadowVerticalOffset: Settings.data.general.shadowOffsetY // Animation duration (ms) - property int animationFaster: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(75 / Settings.data.general.animationSpeed) - property int animationFast: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(150 / Settings.data.general.animationSpeed) - property int animationNormal: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(300 / Settings.data.general.animationSpeed) - property int animationSlow: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(450 / Settings.data.general.animationSpeed) - property int animationSlowest: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(750 / Settings.data.general.animationSpeed) + readonly property int animationFaster: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(75 / Settings.data.general.animationSpeed) + readonly property int animationFast: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(150 / Settings.data.general.animationSpeed) + readonly property int animationNormal: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(300 / Settings.data.general.animationSpeed) + readonly property int animationSlow: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(450 / Settings.data.general.animationSpeed) + readonly property int animationSlowest: (Settings.data.general.animationDisabled || PowerProfileService.noctaliaPerformanceMode) ? 0 : Math.round(750 / Settings.data.general.animationSpeed) // Delays - property int tooltipDelay: 300 - property int tooltipDelayLong: 1200 - property int pillDelay: 500 + readonly property int tooltipDelay: 300 + readonly property int tooltipDelayLong: 1200 + readonly property int pillDelay: 500 // Widgets base size - property real baseWidgetSize: 33 - property real sliderWidth: 200 + readonly property real baseWidgetSize: 33 + readonly property real sliderWidth: 200 - property real uiScaleRatio: Settings.data.general.scaleRatio + readonly property real uiScaleRatio: Settings.data.general.scaleRatio // Bar Dimensions - property real barHeight: { + readonly property real barHeight: { switch (Settings.data.bar.density) { case "mini": - return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 22 : 20 + return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 22 : 20; case "compact": - return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 27 : 25 + return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 27 : 25; case "comfortable": - return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 39 : 37 + return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 39 : 37; default: - case "default": - return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 33 : 31 + return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 33 : 31; } } - property real capsuleHeight: { + readonly property real capsuleHeight: { switch (Settings.data.bar.density) { case "mini": - return Math.round(barHeight * 1.0) + return Math.round(barHeight * 1.0); case "compact": - return Math.round(barHeight * 0.85) + return Math.round(barHeight * 0.85); case "comfortable": - return Math.round(barHeight * 0.73) + return Math.round(barHeight * 0.73); default: - case "default": - return Math.round(barHeight * 0.82) + return Math.round(barHeight * 0.82); } } } diff --git a/Commons/ThemeIcons.qml b/Commons/ThemeIcons.qml index addede93..575f4a3f 100644 --- a/Commons/ThemeIcons.qml +++ b/Commons/ThemeIcons.qml @@ -7,46 +7,46 @@ Singleton { id: root function iconFromName(iconName, fallbackName) { - const fallback = fallbackName || "application-x-executable" + const fallback = fallbackName || "application-x-executable"; try { if (iconName && typeof Quickshell !== 'undefined' && Quickshell.iconPath) { - const p = Quickshell.iconPath(iconName, fallback) + const p = Quickshell.iconPath(iconName, fallback); if (p && p !== "") - return p + return p; } - } catch (e) { + } catch (e) // ignore and fall back - } + {} try { - return Quickshell.iconPath ? (Quickshell.iconPath(fallback, true) || "") : "" + return Quickshell.iconPath ? (Quickshell.iconPath(fallback, true) || "") : ""; } catch (e2) { - return "" + return ""; } } // Resolve icon path for a DesktopEntries appId - safe on missing entries function iconForAppId(appId, fallbackName) { - const fallback = fallbackName || "application-x-executable" + const fallback = fallbackName || "application-x-executable"; if (!appId) - return iconFromName(fallback, fallback) + return iconFromName(fallback, fallback); try { if (typeof DesktopEntries === 'undefined' || !DesktopEntries.byId) - return iconFromName(fallback, fallback) - const entry = (DesktopEntries.heuristicLookup) ? DesktopEntries.heuristicLookup(appId) : DesktopEntries.byId(appId) - const name = entry && entry.icon ? entry.icon : "" - return iconFromName(name || fallback, fallback) + return iconFromName(fallback, fallback); + const entry = (DesktopEntries.heuristicLookup) ? DesktopEntries.heuristicLookup(appId) : DesktopEntries.byId(appId); + const name = entry && entry.icon ? entry.icon : ""; + return iconFromName(name || fallback, fallback); } catch (e) { - return iconFromName(fallback, fallback) + return iconFromName(fallback, fallback); } } // Distro logo helper (absolute path or empty string) function distroLogoPath() { try { - return (typeof OSInfo !== 'undefined' && OSInfo.distroIconPath) ? OSInfo.distroIconPath : "" + return (typeof OSInfo !== 'undefined' && OSInfo.distroIconPath) ? OSInfo.distroIconPath : ""; } catch (e) { - return "" + return ""; } } } diff --git a/Commons/Time.qml b/Commons/Time.qml index b8245808..453da834 100644 --- a/Commons/Time.qml +++ b/Commons/Time.qml @@ -1,7 +1,7 @@ pragma Singleton +import QtQuick import Quickshell -import QtQuick import qs.Commons Singleton { @@ -12,7 +12,7 @@ Singleton { // Returns a Unix Timestamp (in seconds) readonly property int timestamp: { - return Math.floor(root.now / 1000) + return Math.floor(root.now / 1000); } Timer { @@ -22,89 +22,89 @@ Singleton { running: true triggeredOnStart: false onTriggered: { - var newTime = new Date() - root.now = newTime + var newTime = new Date(); + root.now = newTime; // Adjust next interval to sync with the start of the next second - var msIntoSecond = newTime.getMilliseconds() + var msIntoSecond = newTime.getMilliseconds(); if (msIntoSecond > 100) { // If we're more than 100ms into the second, adjust for next time - updateTimer.interval = 1000 - msIntoSecond + 10 // +10ms buffer - updateTimer.restart() + updateTimer.interval = 1000 - msIntoSecond + 10; // +10ms buffer + updateTimer.restart(); } else { - updateTimer.interval = 1000 + updateTimer.interval = 1000; } } } Component.onCompleted: { // Start by syncing to the next second boundary - var now = new Date() - var msUntilNextSecond = 1000 - now.getMilliseconds() - updateTimer.interval = msUntilNextSecond + 10 // +10ms buffer - updateTimer.restart() + var now = new Date(); + var msUntilNextSecond = 1000 - now.getMilliseconds(); + updateTimer.interval = msUntilNextSecond + 10; // +10ms buffer + updateTimer.restart(); } // Formats a Date object into a YYYYMMDD-HHMMSS string. function getFormattedTimestamp(date) { if (!date) { - date = new Date() + date = new Date(); } - const year = date.getFullYear() + const year = date.getFullYear(); // getMonth() is zero-based, so we add 1 - const month = String(date.getMonth() + 1).padStart(2, '0') - const day = String(date.getDate()).padStart(2, '0') + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); - const hours = String(date.getHours()).padStart(2, '0') - const minutes = String(date.getMinutes()).padStart(2, '0') - const seconds = String(date.getSeconds()).padStart(2, '0') + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); - return `${year}${month}${day}-${hours}${minutes}${seconds}` + return `${year}${month}${day}-${hours}${minutes}${seconds}`; } // Format an easy to read approximate duration ex: 4h 32m // Used to display the time remaining on the Battery widget, computer uptime, etc.. function formatVagueHumanReadableDuration(totalSeconds) { if (typeof totalSeconds !== 'number' || totalSeconds < 0) { - return '0s' + return '0s'; } // Floor the input to handle decimal seconds - totalSeconds = Math.floor(totalSeconds) + totalSeconds = Math.floor(totalSeconds); - const days = Math.floor(totalSeconds / 86400) - const hours = Math.floor((totalSeconds % 86400) / 3600) - const minutes = Math.floor((totalSeconds % 3600) / 60) - const seconds = totalSeconds % 60 + const days = Math.floor(totalSeconds / 86400); + const hours = Math.floor((totalSeconds % 86400) / 3600); + const minutes = Math.floor((totalSeconds % 3600) / 60); + const seconds = totalSeconds % 60; - const parts = [] + const parts = []; if (days) - parts.push(`${days}d`) + parts.push(`${days}d`); if (hours) - parts.push(`${hours}h`) + parts.push(`${hours}h`); if (minutes) - parts.push(`${minutes}m`) + parts.push(`${minutes}m`); // Only show seconds if no hours and no minutes if (!hours && !minutes) { - parts.push(`${seconds}s`) + parts.push(`${seconds}s`); } - return parts.join(' ') + return parts.join(' '); } // Format a date into function formatRelativeTime(date) { if (!date) - return "" - const diff = Date.now() - date.getTime() + return ""; + const diff = Date.now() - date.getTime(); if (diff < 60000) - return "now" + return "now"; if (diff < 3600000) - return `${Math.floor(diff / 60000)}m ago` + return `${Math.floor(diff / 60000)}m ago`; if (diff < 86400000) - return `${Math.floor(diff / 3600000)}h ago` - return `${Math.floor(diff / 86400000)}d ago` + return `${Math.floor(diff / 3600000)}h ago`; + return `${Math.floor(diff / 86400000)}d ago`; } } diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 8c01040d..1abe79ab 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -48,17 +48,17 @@ Variants { Component.onCompleted: setWallpaperInitial() Component.onDestruction: { - transitionAnimation.stop() - debounceTimer.stop() - shaderLoader.active = false - currentWallpaper.source = "" - nextWallpaper.source = "" + transitionAnimation.stop(); + debounceTimer.stop(); + shaderLoader.active = false; + currentWallpaper.source = ""; + nextWallpaper.source = ""; } Connections { target: Settings.data.wallpaper function onFillModeChanged() { - fillMode = WallpaperService.getFillModeUniform() + fillMode = WallpaperService.getFillModeUniform(); } } @@ -69,8 +69,8 @@ Variants { if (screenName === modelData.name) { // Update wallpaper display // Set wallpaper immediately on startup - futureWallpaper = path - debounceTimer.restart() + futureWallpaper = path; + debounceTimer.restart(); } } } @@ -80,9 +80,9 @@ Variants { function onDisplayScalesChanged() { // Recalculate image sizes without interrupting startup transition if (isStartupTransition) { - return + return; } - recalculateImageSizes() + recalculateImageSizes(); } } @@ -105,7 +105,7 @@ Variants { running: false repeat: false onTriggered: { - changeWallpaper() + changeWallpaper(); } } @@ -123,18 +123,18 @@ Variants { sourceSize: undefined onStatusChanged: { if (status === Image.Error) { - Logger.w("Current wallpaper failed to load:", source) + Logger.w("Current wallpaper failed to load:", source); } else if (status === Image.Ready && !dimensionsCalculated) { - dimensionsCalculated = true - const optimalSize = calculateOptimalWallpaperSize(implicitWidth, implicitHeight) + dimensionsCalculated = true; + const optimalSize = calculateOptimalWallpaperSize(implicitWidth, implicitHeight); if (optimalSize !== false) { - sourceSize = optimalSize + sourceSize = optimalSize; } } } onSourceChanged: { - dimensionsCalculated = false - sourceSize = undefined + dimensionsCalculated = false; + sourceSize = undefined; } } @@ -152,18 +152,18 @@ Variants { sourceSize: undefined onStatusChanged: { if (status === Image.Error) { - Logger.w("Next wallpaper failed to load:", source) + Logger.w("Next wallpaper failed to load:", source); } else if (status === Image.Ready && !dimensionsCalculated) { - dimensionsCalculated = true - const optimalSize = calculateOptimalWallpaperSize(implicitWidth, implicitHeight) + dimensionsCalculated = true; + const optimalSize = calculateOptimalWallpaperSize(implicitWidth, implicitHeight); if (optimalSize !== false) { - sourceSize = optimalSize + sourceSize = optimalSize; } } } onSourceChanged: { - dimensionsCalculated = false - sourceSize = undefined + dimensionsCalculated = false; + sourceSize = undefined; } } @@ -176,15 +176,15 @@ Variants { sourceComponent: { switch (transitionType) { case "wipe": - return wipeShaderComponent + return wipeShaderComponent; case "disc": - return discShaderComponent + return discShaderComponent; case "stripes": - return stripesShaderComponent + return stripesShaderComponent; case "fade": case "none": default: - return fadeShaderComponent + return fadeShaderComponent; } } } @@ -307,64 +307,64 @@ Variants { easing.type: Easing.InOutCubic onFinished: { // Assign new image to current BEFORE clearing to prevent flicker - const tempSource = nextWallpaper.source - currentWallpaper.source = tempSource - transitionProgress = 0.0 + const tempSource = nextWallpaper.source; + currentWallpaper.source = tempSource; + transitionProgress = 0.0; // Now clear nextWallpaper after currentWallpaper has the new source // Force complete cleanup to free texture memory (~18-25MB per monitor) Qt.callLater(() => { - nextWallpaper.source = "" - nextWallpaper.sourceSize = undefined + nextWallpaper.source = ""; + nextWallpaper.sourceSize = undefined; Qt.callLater(() => { - currentWallpaper.asynchronous = true - }) - }) + currentWallpaper.asynchronous = true; + }); + }); } } // ------------------------------------------------------ function calculateOptimalWallpaperSize(wpWidth, wpHeight) { - const compositorScale = CompositorService.getDisplayScale(modelData.name) - const screenWidth = modelData.width * compositorScale - const screenHeight = modelData.height * compositorScale + const compositorScale = CompositorService.getDisplayScale(modelData.name); + const screenWidth = modelData.width * compositorScale; + const screenHeight = modelData.height * compositorScale; if (wpWidth <= screenWidth || wpHeight <= screenHeight || wpWidth <= 0 || wpHeight <= 0) { // Do not resize if wallpaper is smaller than one of the screen dimension - return + return; } - const imageAspectRatio = wpWidth / wpHeight - var dim = Qt.size(0, 0) + const imageAspectRatio = wpWidth / wpHeight; + var dim = Qt.size(0, 0); if (screenWidth >= screenHeight) { - const w = Math.min(screenWidth, wpWidth) - dim = Qt.size(Math.round(w), Math.round(w / imageAspectRatio)) + const w = Math.min(screenWidth, wpWidth); + dim = Qt.size(Math.round(w), Math.round(w / imageAspectRatio)); } else { - const h = Math.min(screenHeight, wpHeight) - dim = Qt.size(Math.round(h * imageAspectRatio), Math.round(h)) + const h = Math.min(screenHeight, wpHeight); + dim = Qt.size(Math.round(h * imageAspectRatio), Math.round(h)); } - Logger.d("Background", `Wallpaper resized on ${modelData.name} ${screenWidth}x${screenHeight} @ ${compositorScale}x`, "src:", wpWidth, wpHeight, "dst:", dim.width, dim.height) - return dim + Logger.d("Background", `Wallpaper resized on ${modelData.name} ${screenWidth}x${screenHeight} @ ${compositorScale}x`, "src:", wpWidth, wpHeight, "dst:", dim.width, dim.height); + return dim; } // ------------------------------------------------------ function recalculateImageSizes() { // Re-evaluate and apply optimal sourceSize for both images when ready if (currentWallpaper.status === Image.Ready) { - const optimal = calculateOptimalWallpaperSize(currentWallpaper.implicitWidth, currentWallpaper.implicitHeight) + const optimal = calculateOptimalWallpaperSize(currentWallpaper.implicitWidth, currentWallpaper.implicitHeight); if (optimal !== undefined && optimal !== false) { - currentWallpaper.sourceSize = optimal + currentWallpaper.sourceSize = optimal; } else { - currentWallpaper.sourceSize = undefined + currentWallpaper.sourceSize = undefined; } } if (nextWallpaper.status === Image.Ready) { - const optimal2 = calculateOptimalWallpaperSize(nextWallpaper.implicitWidth, nextWallpaper.implicitHeight) + const optimal2 = calculateOptimalWallpaperSize(nextWallpaper.implicitWidth, nextWallpaper.implicitHeight); if (optimal2 !== undefined && optimal2 !== false) { - nextWallpaper.sourceSize = optimal2 + nextWallpaper.sourceSize = optimal2; } else { - nextWallpaper.sourceSize = undefined + nextWallpaper.sourceSize = undefined; } } } @@ -373,104 +373,104 @@ Variants { function setWallpaperInitial() { // On startup, defer assigning wallpaper until the service cache is ready, retries every tick if (!WallpaperService || !WallpaperService.isInitialized) { - Qt.callLater(setWallpaperInitial) - return + Qt.callLater(setWallpaperInitial); + return; } - const wallpaperPath = WallpaperService.getWallpaper(modelData.name) + const wallpaperPath = WallpaperService.getWallpaper(modelData.name); - futureWallpaper = wallpaperPath - performStartupTransition() + futureWallpaper = wallpaperPath; + performStartupTransition(); } // ------------------------------------------------------ function setWallpaperImmediate(source) { - transitionAnimation.stop() - transitionProgress = 0.0 + transitionAnimation.stop(); + transitionProgress = 0.0; // Clear nextWallpaper completely to free texture memory - nextWallpaper.source = "" - nextWallpaper.sourceSize = undefined + nextWallpaper.source = ""; + nextWallpaper.sourceSize = undefined; - currentWallpaper.source = "" + currentWallpaper.source = ""; Qt.callLater(() => { - currentWallpaper.source = source - }) + currentWallpaper.source = source; + }); } // ------------------------------------------------------ function setWallpaperWithTransition(source) { if (source === currentWallpaper.source) { - return + return; } if (transitioning) { // We are interrupting a transition - handle cleanup properly - transitionAnimation.stop() - transitionProgress = 0 + transitionAnimation.stop(); + transitionProgress = 0; // Assign nextWallpaper to currentWallpaper BEFORE clearing to prevent flicker - const newCurrentSource = nextWallpaper.source - currentWallpaper.source = newCurrentSource + const newCurrentSource = nextWallpaper.source; + currentWallpaper.source = newCurrentSource; // Now clear nextWallpaper after current has the new source Qt.callLater(() => { - nextWallpaper.source = "" + nextWallpaper.source = ""; // Now set the next wallpaper after a brief delay Qt.callLater(() => { - nextWallpaper.source = source - currentWallpaper.asynchronous = false - transitionAnimation.start() - }) - }) - return + nextWallpaper.source = source; + currentWallpaper.asynchronous = false; + transitionAnimation.start(); + }); + }); + return; } - nextWallpaper.source = source - currentWallpaper.asynchronous = false - transitionAnimation.start() + nextWallpaper.source = source; + currentWallpaper.asynchronous = false; + transitionAnimation.start(); } // ------------------------------------------------------ // Main method that actually trigger the wallpaper change function changeWallpaper() { // Get the transitionType from the settings - transitionType = Settings.data.wallpaper.transitionType + transitionType = Settings.data.wallpaper.transitionType; if (transitionType == "random") { - var index = Math.floor(Math.random() * allTransitions.length) - transitionType = allTransitions[index] + var index = Math.floor(Math.random() * allTransitions.length); + transitionType = allTransitions[index]; } // Ensure the transition type really exists if (transitionType !== "none" && !allTransitions.includes(transitionType)) { - transitionType = "fade" + transitionType = "fade"; } //Logger.i("Background", "New wallpaper: ", futureWallpaper, "On:", modelData.name, "Transition:", transitionType) switch (transitionType) { case "none": - setWallpaperImmediate(futureWallpaper) - break + setWallpaperImmediate(futureWallpaper); + break; case "wipe": - wipeDirection = Math.random() * 4 - setWallpaperWithTransition(futureWallpaper) - break + wipeDirection = Math.random() * 4; + setWallpaperWithTransition(futureWallpaper); + break; case "disc": - discCenterX = Math.random() - discCenterY = Math.random() - setWallpaperWithTransition(futureWallpaper) - break + discCenterX = Math.random(); + discCenterY = Math.random(); + setWallpaperWithTransition(futureWallpaper); + break; case "stripes": - stripesCount = Math.round(Math.random() * 20 + 4) - stripesAngle = Math.random() * 360 - setWallpaperWithTransition(futureWallpaper) - break + stripesCount = Math.round(Math.random() * 20 + 4); + stripesAngle = Math.random() * 360; + setWallpaperWithTransition(futureWallpaper); + break; default: - setWallpaperWithTransition(futureWallpaper) - break + setWallpaperWithTransition(futureWallpaper); + break; } } @@ -478,46 +478,46 @@ Variants { // Dedicated function for startup animation function performStartupTransition() { // Get the transitionType from the settings - transitionType = Settings.data.wallpaper.transitionType + transitionType = Settings.data.wallpaper.transitionType; if (transitionType == "random") { - var index = Math.floor(Math.random() * allTransitions.length) - transitionType = allTransitions[index] + var index = Math.floor(Math.random() * allTransitions.length); + transitionType = allTransitions[index]; } // Ensure the transition type really exists if (transitionType !== "none" && !allTransitions.includes(transitionType)) { - transitionType = "fade" + transitionType = "fade"; } // Apply transitionType so the shader loader picks the correct shader - this.transitionType = transitionType + this.transitionType = transitionType; switch (transitionType) { case "none": - setWallpaperImmediate(futureWallpaper) - break + setWallpaperImmediate(futureWallpaper); + break; case "wipe": - wipeDirection = Math.random() * 4 - setWallpaperWithTransition(futureWallpaper) - break + wipeDirection = Math.random() * 4; + setWallpaperWithTransition(futureWallpaper); + break; case "disc": // Force center origin for elegant startup animation - discCenterX = 0.5 - discCenterY = 0.5 - setWallpaperWithTransition(futureWallpaper) - break + discCenterX = 0.5; + discCenterY = 0.5; + setWallpaperWithTransition(futureWallpaper); + break; case "stripes": - stripesCount = Math.round(Math.random() * 20 + 4) - stripesAngle = Math.random() * 360 - setWallpaperWithTransition(futureWallpaper) - break + stripesCount = Math.round(Math.random() * 20 + 4); + stripesAngle = Math.random() * 360; + setWallpaperWithTransition(futureWallpaper); + break; default: - setWallpaperWithTransition(futureWallpaper) - break + setWallpaperWithTransition(futureWallpaper); + break; } // Mark startup transition complete - isStartupTransition = false + isStartupTransition = false; } } } diff --git a/Modules/Background/Overview.qml b/Modules/Background/Overview.qml index 9312d969..b76d7142 100644 --- a/Modules/Background/Overview.qml +++ b/Modules/Background/Overview.qml @@ -1,6 +1,6 @@ import QtQuick -import Quickshell import QtQuick.Effects +import Quickshell import Quickshell.Wayland import qs.Commons import qs.Services.Compositor @@ -20,16 +20,16 @@ Loader { Component.onCompleted: { if (modelData) { - Logger.d("Overview", "Loading overview for Niri on", modelData.name) + Logger.d("Overview", "Loading overview for Niri on", modelData.name); } - setWallpaperInitial() + setWallpaperInitial(); } Component.onDestruction: { // Clean up resources to prevent memory leak when overviewEnabled is toggled off - timerDisableFx.stop() - bgImage.layer.enabled = false - bgImage.source = "" + timerDisableFx.stop(); + bgImage.layer.enabled = false; + bgImage.source = ""; } // External state management @@ -37,19 +37,19 @@ Loader { target: WallpaperService function onWallpaperChanged(screenName, path) { if (screenName === modelData.name) { - wallpaper = path + wallpaper = path; } } } function setWallpaperInitial() { if (!WallpaperService || !WallpaperService.isInitialized) { - Qt.callLater(setWallpaperInitial) - return + Qt.callLater(setWallpaperInitial); + return; } - const wallpaperPath = WallpaperService.getWallpaper(modelData.name) + const wallpaperPath = WallpaperService.getWallpaper(modelData.name); if (wallpaperPath && wallpaperPath !== wallpaper) { - wallpaper = wallpaperPath + wallpaper = wallpaperPath; } } diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index b01b83c8..89a72bc7 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -2,13 +2,13 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Wayland import Quickshell.Services.UPower +import Quickshell.Wayland import qs.Commons +import qs.Modules.Bar.Extras +import qs.Modules.Notification import qs.Services.UI import qs.Widgets -import qs.Modules.Notification -import qs.Modules.Bar.Extras // Bar Component Item { @@ -34,9 +34,9 @@ Item { // Register bar when screen becomes available onScreenChanged: { if (screen && screen.name) { - Logger.d("Bar", "Bar screen set to:", screen.name) - Logger.d("Bar", " Position:", barPosition, "Floating:", barFloating) - BarService.registerBar(screen.name) + Logger.d("Bar", "Bar screen set to:", screen.name); + Logger.d("Bar", " Position:", barPosition, "Floating:", barFloating); + BarService.registerBar(screen.name); } } @@ -46,12 +46,12 @@ Item { anchors.fill: parent active: { if (root.screen === null || root.screen === undefined) { - return false + return false; } - var monitors = Settings.data.bar.monitors || [] - var result = monitors.length === 0 || monitors.includes(root.screen.name) - return result + var monitors = Settings.data.bar.monitors || []; + var result = monitors.length === 0 || monitors.includes(root.screen.name); + return result; } sourceComponent: Item { @@ -75,73 +75,73 @@ Item { readonly property int topLeftCornerState: { // Floating bar: always simple rounded corners if (barFloating) - return 0 + return 0; // Top bar: top corners against screen edge = no radius if (barPosition === "top") - return -1 + return -1; // Left bar: top-left against screen edge = no radius if (barPosition === "left") - return -1 + return -1; // Bottom/Right bar with outerCorners: inverted corner if (Settings.data.bar.outerCorners && (barPosition === "bottom" || barPosition === "right")) { - return barIsVertical ? 1 : 2 // horizontal invert for vertical bars, vertical invert for horizontal + return barIsVertical ? 1 : 2; // horizontal invert for vertical bars, vertical invert for horizontal } // No outerCorners = square - return -1 + return -1; } readonly property int topRightCornerState: { // Floating bar: always simple rounded corners if (barFloating) - return 0 + return 0; // Top bar: top corners against screen edge = no radius if (barPosition === "top") - return -1 + return -1; // Right bar: top-right against screen edge = no radius if (barPosition === "right") - return -1 + return -1; // Bottom/Left bar with outerCorners: inverted corner if (Settings.data.bar.outerCorners && (barPosition === "bottom" || barPosition === "left")) { - return barIsVertical ? 1 : 2 + return barIsVertical ? 1 : 2; } // No outerCorners = square - return -1 + return -1; } readonly property int bottomLeftCornerState: { // Floating bar: always simple rounded corners if (barFloating) - return 0 + return 0; // Bottom bar: bottom corners against screen edge = no radius if (barPosition === "bottom") - return -1 + return -1; // Left bar: bottom-left against screen edge = no radius if (barPosition === "left") - return -1 + return -1; // Top/Right bar with outerCorners: inverted corner if (Settings.data.bar.outerCorners && (barPosition === "top" || barPosition === "right")) { - return barIsVertical ? 1 : 2 + return barIsVertical ? 1 : 2; } // No outerCorners = square - return -1 + return -1; } readonly property int bottomRightCornerState: { // Floating bar: always simple rounded corners if (barFloating) - return 0 + return 0; // Bottom bar: bottom corners against screen edge = no radius if (barPosition === "bottom") - return -1 + return -1; // Right bar: bottom-right against screen edge = no radius if (barPosition === "right") - return -1 + return -1; // Top/Left bar with outerCorners: inverted corner if (Settings.data.bar.outerCorners && (barPosition === "top" || barPosition === "left")) { - return barIsVertical ? 1 : 2 + return barIsVertical ? 1 : 2; } // No outerCorners = square - return -1 + return -1; } MouseArea { @@ -151,14 +151,14 @@ Item { preventStealing: true onClicked: function (mouse) { if (mouse.button === Qt.RightButton) { - var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen) + var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen); if (Settings.data.controlCenter.position === "close_to_bar_button") { // Will attempt to open the panel next to the bar button if any. - controlCenterPanel?.toggle(null, "ControlCenter") + controlCenterPanel?.toggle(null, "ControlCenter"); } else { - controlCenterPanel?.toggle() + controlCenterPanel?.toggle(); } - mouse.accepted = true + mouse.accepted = true; } } } diff --git a/Modules/Bar/Extras/BarExclusionZone.qml b/Modules/Bar/Extras/BarExclusionZone.qml index a2448a92..6d73fba2 100644 --- a/Modules/Bar/Extras/BarExclusionZone.qml +++ b/Modules/Bar/Extras/BarExclusionZone.qml @@ -3,13 +3,12 @@ import Quickshell import Quickshell.Wayland import qs.Commons - /** - * BarExclusionZone - Invisible PanelWindow that reserves exclusive space for the bar - * - * This is a minimal window that works with the compositor to reserve space, - * while the actual bar UI is rendered in NFullScreenWindow. - */ +* BarExclusionZone - Invisible PanelWindow that reserves exclusive space for the bar +* +* This is a minimal window that works with the compositor to reserve space, +* while the actual bar UI is rendered in NFullScreenWindow. +*/ PanelWindow { id: root @@ -46,11 +45,11 @@ PanelWindow { // Vertical bar: reserve bar height + margin on the anchored edge only if (barFloating) { // For left bar, reserve left margin; for right bar, reserve right margin - return Style.barHeight + barMarginH + return Style.barHeight + barMarginH; } - return Style.barHeight + return Style.barHeight; } - return 0 // Auto-width when left/right anchors are true + return 0; // Auto-width when left/right anchors are true } implicitHeight: { @@ -58,17 +57,17 @@ PanelWindow { // Horizontal bar: reserve bar height + margin on the anchored edge only if (barFloating) { // For top bar, reserve top margin; for bottom bar, reserve bottom margin - return Style.barHeight + barMarginV + return Style.barHeight + barMarginV; } - return Style.barHeight + return Style.barHeight; } - return 0 // Auto-height when top/bottom anchors are true + return 0; // Auto-height when top/bottom anchors are true } Component.onCompleted: { - Logger.d("BarExclusionZone", "Created for screen:", screen?.name) - Logger.d("BarExclusionZone", " Position:", barPosition, "Exclusive:", exclusive, "Floating:", barFloating) - Logger.d("BarExclusionZone", " Anchors - top:", anchors.top, "bottom:", anchors.bottom, "left:", anchors.left, "right:", anchors.right) - Logger.d("BarExclusionZone", " Size:", width, "x", height, "implicitWidth:", implicitWidth, "implicitHeight:", implicitHeight) + Logger.d("BarExclusionZone", "Created for screen:", screen?.name); + Logger.d("BarExclusionZone", " Position:", barPosition, "Exclusive:", exclusive, "Floating:", barFloating); + Logger.d("BarExclusionZone", " Anchors - top:", anchors.top, "bottom:", anchors.bottom, "left:", anchors.left, "right:", anchors.right); + Logger.d("BarExclusionZone", " Size:", width, "x", height, "implicitWidth:", implicitWidth, "implicitHeight:", implicitHeight); } } diff --git a/Modules/Bar/Extras/BarPill.qml b/Modules/Bar/Extras/BarPill.qml index a8c097cf..a50041ca 100644 --- a/Modules/Bar/Extras/BarPill.qml +++ b/Modules/Bar/Extras/BarPill.qml @@ -92,19 +92,19 @@ Item { function show() { if (pillLoader.item && pillLoader.item.show) { - pillLoader.item.show() + pillLoader.item.show(); } } function hide() { if (pillLoader.item && pillLoader.item.hide) { - pillLoader.item.hide() + pillLoader.item.hide(); } } function showDelayed() { if (pillLoader.item && pillLoader.item.showDelayed) { - pillLoader.item.showDelayed() + pillLoader.item.showDelayed(); } } } diff --git a/Modules/Bar/Extras/BarPillHorizontal.qml b/Modules/Bar/Extras/BarPillHorizontal.qml index ed74b74b..b799884a 100644 --- a/Modules/Bar/Extras/BarPillHorizontal.qml +++ b/Modules/Bar/Extras/BarPillHorizontal.qml @@ -45,18 +45,18 @@ Item { readonly property real iconSize: { switch (root.density) { case "compact": - return Math.max(1, Math.round(pillHeight * 0.65)) + return Math.max(1, Math.round(pillHeight * 0.65)); default: - return Math.max(1, Math.round(pillHeight * 0.48)) + return Math.max(1, Math.round(pillHeight * 0.48)); } } readonly property real textSize: { switch (root.density) { case "compact": - return Math.max(1, Math.round(pillHeight * 0.45)) + return Math.max(1, Math.round(pillHeight * 0.45)); default: - return Math.max(1, Math.round(pillHeight * 0.33)) + return Math.max(1, Math.round(pillHeight * 0.33)); } } @@ -67,7 +67,7 @@ Item { target: root function onTooltipTextChanged() { if (hovered) { - TooltipService.updateText(root.tooltipText) + TooltipService.updateText(root.tooltipText); } } } @@ -97,13 +97,13 @@ Item { anchors.verticalCenter: parent.verticalCenter x: { // Better text horizontal centering - var centerX = (parent.width - width) / 2 - var offset = oppositeDirection ? Style.marginXS : -Style.marginXS + var centerX = (parent.width - width) / 2; + var offset = oppositeDirection ? Style.marginXS : -Style.marginXS; if (forceOpen) { // If its force open, the icon disc background is the same color as the bg pill move text slightly - offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS + offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS; } - return centerX + offset + return centerX + offset; } text: root.text + root.suffix family: Settings.data.ui.fontFixed @@ -179,11 +179,11 @@ Item { easing.type: Easing.OutCubic } onStarted: { - showPill = true + showPill = true; } onStopped: { - delayedHideAnim.start() - root.shown() + delayedHideAnim.start(); + root.shown(); } } @@ -195,7 +195,7 @@ Item { } ScriptAction { script: if (shouldAnimateHide) { - hideAnim.start() + hideAnim.start(); } } } @@ -220,9 +220,9 @@ Item { easing.type: Easing.InCubic } onStopped: { - showPill = false - shouldAnimateHide = false - root.hidden() + showPill = false; + shouldAnimateHide = false; + root.hidden(); } } @@ -231,7 +231,7 @@ Item { interval: Style.pillDelay onTriggered: { if (!showPill) { - showAnim.start() + showAnim.start(); } } } @@ -241,31 +241,31 @@ Item { hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton onEntered: { - hovered = true - root.entered() - TooltipService.show(Screen, pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong) + hovered = true; + root.entered(); + TooltipService.show(Screen, pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong); if (forceClose) { - return + return; } if (!forceOpen) { - showDelayed() + showDelayed(); } } onExited: { - hovered = false - root.exited() + hovered = false; + root.exited(); if (!forceOpen && !forceClose) { - hide() + hide(); } - TooltipService.hide() + TooltipService.hide(); } onClicked: function (mouse) { if (mouse.button === Qt.LeftButton) { - root.clicked() + root.clicked(); } else if (mouse.button === Qt.RightButton) { - root.rightClicked() + root.rightClicked(); } else if (mouse.button === Qt.MiddleButton) { - root.middleClicked() + root.middleClicked(); } } onWheel: wheel => root.wheel(wheel.angleDelta.y) @@ -273,43 +273,43 @@ Item { function show() { if (!showPill) { - shouldAnimateHide = autoHide - showAnim.start() + shouldAnimateHide = autoHide; + showAnim.start(); } else { - hideAnim.stop() - delayedHideAnim.restart() + hideAnim.stop(); + delayedHideAnim.restart(); } } function hide() { if (forceOpen) { - return + return; } if (showPill) { - hideAnim.start() + hideAnim.start(); } - showTimer.stop() + showTimer.stop(); } function showDelayed() { if (!showPill) { - shouldAnimateHide = autoHide - showTimer.start() + shouldAnimateHide = autoHide; + showTimer.start(); } else { - hideAnim.stop() - delayedHideAnim.restart() + hideAnim.stop(); + delayedHideAnim.restart(); } } onForceOpenChanged: { if (forceOpen) { // Immediately lock open without animations - showAnim.stop() - hideAnim.stop() - delayedHideAnim.stop() - showPill = true + showAnim.stop(); + hideAnim.stop(); + delayedHideAnim.stop(); + showPill = true; } else { - hide() + hide(); } } } diff --git a/Modules/Bar/Extras/BarPillVertical.qml b/Modules/Bar/Extras/BarPillVertical.qml index 5718c619..db5de028 100644 --- a/Modules/Bar/Extras/BarPillVertical.qml +++ b/Modules/Bar/Extras/BarPillVertical.qml @@ -55,18 +55,18 @@ Item { readonly property real iconSize: { switch (root.density) { case "compact": - return Math.max(1, Math.round(pillHeight * 0.65)) + return Math.max(1, Math.round(pillHeight * 0.65)); default: - return Math.max(1, Math.round(pillHeight * 0.48)) + return Math.max(1, Math.round(pillHeight * 0.48)); } } readonly property real textSize: { switch (root.density) { case "compact": - return Math.max(1, Math.round(pillHeight * 0.38)) + return Math.max(1, Math.round(pillHeight * 0.38)); default: - return Math.max(1, Math.round(pillHeight * 0.33)) + return Math.max(1, Math.round(pillHeight * 0.33)); } } @@ -78,7 +78,7 @@ Item { target: root function onTooltipTextChanged() { if (hovered) { - TooltipService.updateText(root.tooltipText) + TooltipService.updateText(root.tooltipText); } } } @@ -123,11 +123,11 @@ Item { visible: revealed function getVerticalCenterOffset() { - var offset = openDownward ? Math.round(pillPaddingVertical * 0.75) : -Math.round(pillPaddingVertical * 0.75) + var offset = openDownward ? Math.round(pillPaddingVertical * 0.75) : -Math.round(pillPaddingVertical * 0.75); if (forceOpen) { - offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS + offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS; } - return offset + return offset; } } Behavior on width { @@ -212,11 +212,11 @@ Item { easing.type: Easing.OutCubic } onStarted: { - showPill = true + showPill = true; } onStopped: { - delayedHideAnim.start() - root.shown() + delayedHideAnim.start(); + root.shown(); } } @@ -228,7 +228,7 @@ Item { } ScriptAction { script: if (shouldAnimateHide) { - hideAnim.start() + hideAnim.start(); } } } @@ -261,9 +261,9 @@ Item { easing.type: Easing.InCubic } onStopped: { - showPill = false - shouldAnimateHide = false - root.hidden() + showPill = false; + shouldAnimateHide = false; + root.hidden(); } } @@ -272,7 +272,7 @@ Item { interval: Style.pillDelay onTriggered: { if (!showPill) { - showAnim.start() + showAnim.start(); } } } @@ -282,31 +282,31 @@ Item { hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton onEntered: { - hovered = true - root.entered() - TooltipService.show(Screen, pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong) + hovered = true; + root.entered(); + TooltipService.show(Screen, pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong); if (forceClose) { - return + return; } if (!forceOpen) { - showDelayed() + showDelayed(); } } onExited: { - hovered = false - root.exited() + hovered = false; + root.exited(); if (!forceOpen && !forceClose) { - hide() + hide(); } - TooltipService.hide() + TooltipService.hide(); } onClicked: function (mouse) { if (mouse.button === Qt.LeftButton) { - root.clicked() + root.clicked(); } else if (mouse.button === Qt.RightButton) { - root.rightClicked() + root.rightClicked(); } else if (mouse.button === Qt.MiddleButton) { - root.middleClicked() + root.middleClicked(); } } onWheel: wheel => root.wheel(wheel.angleDelta.y) @@ -314,43 +314,43 @@ Item { function show() { if (!showPill) { - shouldAnimateHide = autoHide - showAnim.start() + shouldAnimateHide = autoHide; + showAnim.start(); } else { - hideAnim.stop() - delayedHideAnim.restart() + hideAnim.stop(); + delayedHideAnim.restart(); } } function hide() { if (forceOpen) { - return + return; } if (showPill) { - hideAnim.start() + hideAnim.start(); } - showTimer.stop() + showTimer.stop(); } function showDelayed() { if (!showPill) { - shouldAnimateHide = autoHide - showTimer.start() + shouldAnimateHide = autoHide; + showTimer.start(); } else { - hideAnim.stop() - delayedHideAnim.restart() + hideAnim.stop(); + delayedHideAnim.restart(); } } onForceOpenChanged: { if (forceOpen) { // Immediately lock open without animations - showAnim.stop() - hideAnim.stop() - delayedHideAnim.stop() - showPill = true + showAnim.stop(); + hideAnim.stop(); + delayedHideAnim.stop(); + showPill = true; } else { - hide() + hide(); } } } diff --git a/Modules/Bar/Extras/BarWidgetLoader.qml b/Modules/Bar/Extras/BarWidgetLoader.qml index 4737f8dc..99ba181e 100644 --- a/Modules/Bar/Extras/BarWidgetLoader.qml +++ b/Modules/Bar/Extras/BarWidgetLoader.qml @@ -1,7 +1,7 @@ import QtQuick import Quickshell -import qs.Services.UI import qs.Commons +import qs.Services.UI Item { id: root @@ -25,7 +25,7 @@ Item { visible: loader.item ? ((loader.item.opacity > 0.0) || (loader.item.hasOwnProperty("hideMode") && loader.item.hideMode === "transparent")) : false function getImplicitSize(item, prop) { - return (item && item.visible) ? Math.round(item[prop]) : 0 + return (item && item.visible) ? Math.round(item[prop]) : 0; } Loader { @@ -36,42 +36,41 @@ Item { onLoaded: { if (!item) - return - - Logger.d("BarWidgetLoader", "Loading widget", widgetId, "on screen:", widgetScreen.name) + return; + Logger.d("BarWidgetLoader", "Loading widget", widgetId, "on screen:", widgetScreen.name); // Apply properties to loaded widget for (var prop in widgetProps) { if (item.hasOwnProperty(prop)) { - item[prop] = widgetProps[prop] + item[prop] = widgetProps[prop]; } } // Set screen property if (item.hasOwnProperty("screen")) { - item.screen = widgetScreen + item.screen = widgetScreen; } // Set scaling property if (item.hasOwnProperty("scaling")) { item.scaling = Qt.binding(function () { - return root.scaling - }) + return root.scaling; + }); } // Register this widget instance with BarService - BarService.registerWidget(widgetScreen.name, section, widgetId, sectionIndex, item) + BarService.registerWidget(widgetScreen.name, section, widgetId, sectionIndex, item); // Call custom onLoaded if it exists if (item.hasOwnProperty("onLoaded")) { - item.onLoaded() + item.onLoaded(); } } Component.onDestruction: { // Unregister when destroyed if (widgetScreen && section) { - BarService.unregisterWidget(widgetScreen.name, section, widgetId, sectionIndex) + BarService.unregisterWidget(widgetScreen.name, section, widgetId, sectionIndex); } } } @@ -79,7 +78,7 @@ Item { // Error handling Component.onCompleted: { if (!BarWidgetRegistry.hasWidget(widgetId)) { - Logger.w("BarWidgetLoader", "Widget not found in registry:", widgetId) + Logger.w("BarWidgetLoader", "Widget not found in registry:", widgetId); } } } diff --git a/Modules/Bar/Extras/TrayMenu.qml b/Modules/Bar/Extras/TrayMenu.qml index 53c5cd37..84d181d6 100644 --- a/Modules/Bar/Extras/TrayMenu.qml +++ b/Modules/Bar/Extras/TrayMenu.qml @@ -25,20 +25,20 @@ PopupWindow { // Compute if current tray item is pinned readonly property bool isPinned: { if (!trayItem || widgetSection === "" || widgetIndex < 0) - return false - var widgets = Settings.data.bar.widgets[widgetSection] + return false; + var widgets = Settings.data.bar.widgets[widgetSection]; if (!widgets || widgetIndex >= widgets.length) - return false - var widgetSettings = widgets[widgetIndex] + return false; + var widgetSettings = widgets[widgetIndex]; if (!widgetSettings || widgetSettings.id !== "Tray") - return false - var pinnedList = widgetSettings.pinned || [] - const itemName = trayItem.tooltipTitle || trayItem.name || trayItem.id || "" + return false; + var pinnedList = widgetSettings.pinned || []; + const itemName = trayItem.tooltipTitle || trayItem.name || trayItem.id || ""; for (var i = 0; i < pinnedList.length; i++) { if (pinnedList[i] === itemName) - return true + return true; } - return false + return false; } readonly property int menuWidth: 220 @@ -53,47 +53,47 @@ PopupWindow { anchor.rect.x: anchorX anchor.rect.y: { if (isSubMenu) { - const offsetY = Settings.data.bar.position === "bottom" ? -10 : 10 - return anchorY + offsetY + const offsetY = Settings.data.bar.position === "bottom" ? -10 : 10; + return anchorY + offsetY; } - return anchorY + Settings.data.bar.position === "bottom" ? -implicitHeight : Style.barHeight + return anchorY + Settings.data.bar.position === "bottom" ? -implicitHeight : Style.barHeight; } function showAt(item, x, y) { if (!item) { - Logger.w("TrayMenu", "anchorItem is undefined, won't show menu.") - return + Logger.w("TrayMenu", "anchorItem is undefined, won't show menu."); + return; } if (!opener.children || opener.children.values.length === 0) { //Logger.w("TrayMenu", "Menu not ready, delaying show") - Qt.callLater(() => showAt(item, x, y)) - return + Qt.callLater(() => showAt(item, x, y)); + return; } - anchorItem = item - anchorX = x - anchorY = y + anchorItem = item; + anchorX = x; + anchorY = y; - visible = true - forceActiveFocus() + visible = true; + forceActiveFocus(); // Force update after showing. Qt.callLater(() => { - root.anchor.updateAnchor() - }) + root.anchor.updateAnchor(); + }); } function hideMenu() { - visible = false + visible = false; // Clean up all submenus recursively for (var i = 0; i < columnLayout.children.length; i++) { - const child = columnLayout.children[i] + const child = columnLayout.children[i]; if (child?.subMenu) { - child.subMenu.hideMenu() - child.subMenu.destroy() - child.subMenu = null + child.subMenu.hideMenu(); + child.subMenu.destroy(); + child.subMenu = null; } } } @@ -166,11 +166,11 @@ PopupWindow { Layout.preferredWidth: parent.width Layout.preferredHeight: { if (modelData?.isSeparator) { - return 8 + return 8; } else { // Calculate based on text content - const textHeight = text.contentHeight || (Style.fontSizeS * 1.2) - return Math.max(28, textHeight + (Style.marginS * 2)) + const textHeight = text.contentHeight || (Style.fontSizeS * 1.2); + return Math.max(28, textHeight + (Style.marginS * 2)); } } @@ -237,31 +237,31 @@ PopupWindow { // Click on items with children toggles submenu if (entry.subMenu) { // Close existing submenu - entry.subMenu.hideMenu() - entry.subMenu.destroy() - entry.subMenu = null + entry.subMenu.hideMenu(); + entry.subMenu.destroy(); + entry.subMenu = null; } else { // Close any other open submenus first for (var i = 0; i < columnLayout.children.length; i++) { - const sibling = columnLayout.children[i] + const sibling = columnLayout.children[i]; if (sibling !== entry && sibling.subMenu) { - sibling.subMenu.hideMenu() - sibling.subMenu.destroy() - sibling.subMenu = null + sibling.subMenu.hideMenu(); + sibling.subMenu.destroy(); + sibling.subMenu = null; } } // Determine submenu opening direction - let openLeft = false - const barPosition = Settings.data.bar.position - const globalPos = entry.mapToItem(null, 0, 0) + let openLeft = false; + const barPosition = Settings.data.bar.position; + const globalPos = entry.mapToItem(null, 0, 0); if (barPosition === "right") { - openLeft = true + openLeft = true; } else if (barPosition === "left") { - openLeft = false + openLeft = false; } else { - openLeft = (root.widgetSection === "right") + openLeft = (root.widgetSection === "right"); } // Open new submenu @@ -269,30 +269,30 @@ PopupWindow { "menu": modelData, "isSubMenu": true, "screen": root.screen - }) + }); if (entry.subMenu) { - const overlap = 60 - entry.subMenu.anchorItem = entry - entry.subMenu.anchorX = openLeft ? -overlap : overlap - entry.subMenu.anchorY = 0 - entry.subMenu.visible = true + const overlap = 60; + entry.subMenu.anchorItem = entry; + entry.subMenu.anchorX = openLeft ? -overlap : overlap; + entry.subMenu.anchorY = 0; + entry.subMenu.visible = true; // Force anchor update with new position Qt.callLater(() => { - entry.subMenu.anchor.updateAnchor() - }) + entry.subMenu.anchor.updateAnchor(); + }); } } } else { // Click on regular items triggers them - modelData.triggered() - root.hideMenu() + modelData.triggered(); + root.hideMenu(); // Close the drawer if it's open if (root.screen) { - const panel = PanelService.getPanel("trayDrawerPanel", root.screen) + const panel = PanelService.getPanel("trayDrawerPanel", root.screen); if (panel && panel.visible) { - panel.close() + panel.close(); } } } @@ -303,8 +303,8 @@ PopupWindow { Component.onDestruction: { if (subMenu) { - subMenu.destroy() - subMenu = null + subMenu.destroy(); + subMenu = null; } } } @@ -351,9 +351,9 @@ PopupWindow { onClicked: { if (root.isPinned) { - root.removeFromPinned() + root.removeFromPinned(); } else { - root.addToPinned() + root.addToPinned(); } } } @@ -363,72 +363,72 @@ PopupWindow { function addToPinned() { if (!trayItem || widgetSection === "" || widgetIndex < 0) { - Logger.w("TrayMenu", "Cannot pin: missing tray item or widget info") - return + Logger.w("TrayMenu", "Cannot pin: missing tray item or widget info"); + return; } - const itemName = trayItem.tooltipTitle || trayItem.name || trayItem.id || "" + const itemName = trayItem.tooltipTitle || trayItem.name || trayItem.id || ""; if (!itemName) { - Logger.w("TrayMenu", "Cannot pin: tray item has no name") - return + Logger.w("TrayMenu", "Cannot pin: tray item has no name"); + return; } - var widgets = Settings.data.bar.widgets[widgetSection] + var widgets = Settings.data.bar.widgets[widgetSection]; if (!widgets || widgetIndex >= widgets.length) { - Logger.w("TrayMenu", "Cannot pin: invalid widget index") - return + Logger.w("TrayMenu", "Cannot pin: invalid widget index"); + return; } - var widgetSettings = widgets[widgetIndex] + var widgetSettings = widgets[widgetIndex]; if (!widgetSettings || widgetSettings.id !== "Tray") { - Logger.w("TrayMenu", "Cannot pin: widget is not a Tray widget") - return + Logger.w("TrayMenu", "Cannot pin: widget is not a Tray widget"); + return; } - var pinnedList = widgetSettings.pinned || [] - var newPinned = pinnedList.slice() - newPinned.push(itemName) - var newSettings = Object.assign({}, widgetSettings) - newSettings.pinned = newPinned - widgets[widgetIndex] = newSettings - Settings.data.bar.widgets[widgetSection] = widgets - Settings.saveImmediate() + var pinnedList = widgetSettings.pinned || []; + var newPinned = pinnedList.slice(); + newPinned.push(itemName); + var newSettings = Object.assign({}, widgetSettings); + newSettings.pinned = newPinned; + widgets[widgetIndex] = newSettings; + Settings.data.bar.widgets[widgetSection] = widgets; + Settings.saveImmediate(); // Close drawer when pinning (drawer needs to resize) if (screen) { - const panel = PanelService.getPanel("trayDrawerPanel", screen) + const panel = PanelService.getPanel("trayDrawerPanel", screen); if (panel) - panel.close() + panel.close(); } } function removeFromPinned() { if (!trayItem || widgetSection === "" || widgetIndex < 0) { - Logger.w("TrayMenu", "Cannot unpin: missing tray item or widget info") - return + Logger.w("TrayMenu", "Cannot unpin: missing tray item or widget info"); + return; } - const itemName = trayItem.tooltipTitle || trayItem.name || trayItem.id || "" + const itemName = trayItem.tooltipTitle || trayItem.name || trayItem.id || ""; if (!itemName) { - Logger.w("TrayMenu", "Cannot unpin: tray item has no name") - return + Logger.w("TrayMenu", "Cannot unpin: tray item has no name"); + return; } - var widgets = Settings.data.bar.widgets[widgetSection] + var widgets = Settings.data.bar.widgets[widgetSection]; if (!widgets || widgetIndex >= widgets.length) { - Logger.w("TrayMenu", "Cannot unpin: invalid widget index") - return + Logger.w("TrayMenu", "Cannot unpin: invalid widget index"); + return; } - var widgetSettings = widgets[widgetIndex] + var widgetSettings = widgets[widgetIndex]; if (!widgetSettings || widgetSettings.id !== "Tray") { - Logger.w("TrayMenu", "Cannot unpin: widget is not a Tray widget") - return + Logger.w("TrayMenu", "Cannot unpin: widget is not a Tray widget"); + return; } - var pinnedList = widgetSettings.pinned || [] - var newPinned = [] + var pinnedList = widgetSettings.pinned || []; + var newPinned = []; for (var i = 0; i < pinnedList.length; i++) { if (pinnedList[i] !== itemName) { - newPinned.push(pinnedList[i]) + newPinned.push(pinnedList[i]); } } - var newSettings = Object.assign({}, widgetSettings) - newSettings.pinned = newPinned - widgets[widgetIndex] = newSettings - Settings.data.bar.widgets[widgetSection] = widgets - Settings.saveImmediate() + var newSettings = Object.assign({}, widgetSettings); + newSettings.pinned = newPinned; + widgets[widgetIndex] = newSettings; + Settings.data.bar.widgets[widgetSection] = widgets; + Settings.saveImmediate(); } } diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index 7687dfc2..6d17d4c4 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -23,12 +23,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } // Widget settings - matching MediaMini pattern @@ -73,60 +73,60 @@ Item { } function calculatedVerticalDimension() { - return Math.round((Style.baseWidgetSize - 5) * scaling) + return Math.round((Style.baseWidgetSize - 5) * scaling); } function calculateContentWidth() { // Calculate the actual content width based on visible elements - var contentWidth = 0 - var margins = Style.marginS * scaling * 2 // Left and right margins + var contentWidth = 0; + var margins = Style.marginS * scaling * 2; // Left and right margins // Icon width (if visible) if (showIcon) { - contentWidth += 18 * scaling - contentWidth += Style.marginS * scaling // Spacing after icon + contentWidth += 18 * scaling; + contentWidth += Style.marginS * scaling; // Spacing after icon } // Text width (use the measured width) - contentWidth += fullTitleMetrics.contentWidth + contentWidth += fullTitleMetrics.contentWidth; // Additional small margin for text - contentWidth += Style.marginXXS * 2 + contentWidth += Style.marginXXS * 2; // Add container margins - contentWidth += margins + contentWidth += margins; - return Math.ceil(contentWidth) + return Math.ceil(contentWidth); } // Dynamic width: adapt to content but respect maximum width setting readonly property real dynamicWidth: { // If using fixed width mode, always use maxWidth if (useFixedWidth) { - return maxWidth + return maxWidth; } // Otherwise, adapt to content if (!hasFocusedWindow) { - return Math.min(calculateContentWidth(), maxWidth) + return Math.min(calculateContentWidth(), maxWidth); } // Use content width but don't exceed user-set maximum width - return Math.min(calculateContentWidth(), maxWidth) + return Math.min(calculateContentWidth(), maxWidth); } function getAppIcon() { try { // Try CompositorService first - const focusedWindow = CompositorService.getFocusedWindow() + const focusedWindow = CompositorService.getFocusedWindow(); if (focusedWindow && focusedWindow.appId) { try { - const idValue = focusedWindow.appId - const normalizedId = (typeof idValue === 'string') ? idValue : String(idValue) - const iconResult = ThemeIcons.iconForAppId(normalizedId.toLowerCase()) + const idValue = focusedWindow.appId; + const normalizedId = (typeof idValue === 'string') ? idValue : String(idValue); + const iconResult = ThemeIcons.iconForAppId(normalizedId.toLowerCase()); if (iconResult && iconResult !== "") { - return iconResult + return iconResult; } } catch (iconError) { - Logger.w("ActiveWindow", "Error getting icon from CompositorService:", iconError) + Logger.w("ActiveWindow", "Error getting icon from CompositorService:", iconError); } } @@ -134,25 +134,25 @@ Item { // Fallback to ToplevelManager if (ToplevelManager && ToplevelManager.activeToplevel) { try { - const activeToplevel = ToplevelManager.activeToplevel + const activeToplevel = ToplevelManager.activeToplevel; if (activeToplevel.appId) { - const idValue2 = activeToplevel.appId - const normalizedId2 = (typeof idValue2 === 'string') ? idValue2 : String(idValue2) - const iconResult2 = ThemeIcons.iconForAppId(normalizedId2.toLowerCase()) + const idValue2 = activeToplevel.appId; + const normalizedId2 = (typeof idValue2 === 'string') ? idValue2 : String(idValue2); + const iconResult2 = ThemeIcons.iconForAppId(normalizedId2.toLowerCase()); if (iconResult2 && iconResult2 !== "") { - return iconResult2 + return iconResult2; } } } catch (fallbackError) { - Logger.w("ActiveWindow", "Error getting icon from ToplevelManager:", fallbackError) + Logger.w("ActiveWindow", "Error getting icon from ToplevelManager:", fallbackError); } } } - return ThemeIcons.iconFromName(fallbackIcon) + return ThemeIcons.iconFromName(fallbackIcon); } catch (e) { - Logger.w("ActiveWindow", "Error in getAppIcon:", e) - return ThemeIcons.iconFromName(fallbackIcon) + Logger.w("ActiveWindow", "Error in getAppIcon:", e); + return ThemeIcons.iconFromName(fallbackIcon); } } @@ -228,10 +228,10 @@ Item { id: titleContainer Layout.preferredWidth: { // Calculate available width based on other elements - var iconWidth = (showIcon && windowIcon.visible ? (18 + Style.marginS) : 0) - var totalMargins = Style.marginXXS * 2 - var availableWidth = mainContainer.width - iconWidth - totalMargins - return Math.max(20, availableWidth) + var iconWidth = (showIcon && windowIcon.visible ? (18 + Style.marginS) : 0); + var totalMargins = Style.marginXXS * 2; + var availableWidth = mainContainer.width - iconWidth - totalMargins; + return Math.max(20, availableWidth); } Layout.maximumWidth: Layout.preferredWidth Layout.alignment: Qt.AlignVCenter @@ -252,8 +252,8 @@ Item { repeat: false onTriggered: { if (scrollingMode === "always" && titleContainer.needsScrolling) { - titleContainer.isScrolling = true - titleContainer.isResetting = false + titleContainer.isScrolling = true; + titleContainer.isResetting = false; } } } @@ -261,29 +261,29 @@ Item { // Update scrolling state based on mode property var updateScrollingState: function () { if (scrollingMode === "never") { - isScrolling = false - isResetting = false + isScrolling = false; + isResetting = false; } else if (scrollingMode === "always") { if (needsScrolling) { if (mouseArea.containsMouse) { - isScrolling = false - isResetting = true + isScrolling = false; + isResetting = true; } else { - scrollStartTimer.restart() + scrollStartTimer.restart(); } } else { - scrollStartTimer.stop() - isScrolling = false - isResetting = false + scrollStartTimer.stop(); + isScrolling = false; + isResetting = false; } } else if (scrollingMode === "hover") { if (mouseArea.containsMouse && needsScrolling) { - isScrolling = true - isResetting = false + isScrolling = true; + isResetting = false; } else { - isScrolling = false + isScrolling = false; if (needsScrolling) { - isResetting = true + isResetting = true; } } } @@ -296,7 +296,7 @@ Item { Connections { target: mouseArea function onContainsMouseChanged() { - titleContainer.updateScrollingState() + titleContainer.updateScrollingState(); } } @@ -322,10 +322,10 @@ Item { color: Color.mOnSurface onTextChanged: { if (root.scrollingMode === "always") { - titleContainer.isScrolling = false - titleContainer.isResetting = false - scrollContainer.scrollX = 0 - scrollStartTimer.restart() + titleContainer.isScrolling = false; + titleContainer.isResetting = false; + scrollContainer.scrollX = 0; + scrollStartTimer.restart(); } } } @@ -349,7 +349,7 @@ Item { duration: 300 easing.type: Easing.OutQuad onFinished: { - titleContainer.isResetting = false + titleContainer.isResetting = false; } } @@ -412,11 +412,11 @@ Item { acceptedButtons: Qt.LeftButton onEntered: { if ((windowTitle !== "") && isVerticalBar || (scrollingMode === "never")) { - TooltipService.show(Screen, root, windowTitle, BarService.getTooltipDirection()) + TooltipService.show(Screen, root, windowTitle, BarService.getTooltipDirection()); } } onExited: { - TooltipService.hide() + TooltipService.hide(); } } } @@ -426,18 +426,18 @@ Item { target: CompositorService function onActiveWindowChanged() { try { - windowIcon.source = Qt.binding(getAppIcon) - windowIconVertical.source = Qt.binding(getAppIcon) + windowIcon.source = Qt.binding(getAppIcon); + windowIconVertical.source = Qt.binding(getAppIcon); } catch (e) { - Logger.w("ActiveWindow", "Error in onActiveWindowChanged:", e) + Logger.w("ActiveWindow", "Error in onActiveWindowChanged:", e); } } function onWindowListChanged() { try { - windowIcon.source = Qt.binding(getAppIcon) - windowIconVertical.source = Qt.binding(getAppIcon) + windowIcon.source = Qt.binding(getAppIcon); + windowIconVertical.source = Qt.binding(getAppIcon); } catch (e) { - Logger.w("ActiveWindow", "Error in onWindowListChanged:", e) + Logger.w("ActiveWindow", "Error in onWindowListChanged:", e); } } } diff --git a/Modules/Bar/Widgets/AudioVisualizer.qml b/Modules/Bar/Widgets/AudioVisualizer.qml index cecc6952..2bedeee2 100644 --- a/Modules/Bar/Widgets/AudioVisualizer.qml +++ b/Modules/Bar/Widgets/AudioVisualizer.qml @@ -1,8 +1,8 @@ import QtQuick import Quickshell import qs.Commons -import qs.Services.UI import qs.Services.Media +import qs.Services.UI import qs.Widgets import qs.Widgets.AudioSpectrum @@ -22,12 +22,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } // Resolve settings: try user settings or defaults from BarWidgetRegistry @@ -38,16 +38,16 @@ Item { readonly property color fillColor: { switch (colorName) { case "primary": - return Color.mPrimary + return Color.mPrimary; case "secondary": - return Color.mSecondary + return Color.mSecondary; case "tertiary": - return Color.mTertiary + return Color.mTertiary; case "error": - return Color.mError + return Color.mError; case "onSurface": default: - return Color.mOnSurface + return Color.mOnSurface; } } @@ -92,13 +92,13 @@ Item { sourceComponent: { switch (currentVisualizerType) { case "linear": - return linearComponent + return linearComponent; case "mirrored": - return mirroredComponent + return mirroredComponent; case "wave": - return waveComponent + return waveComponent; default: - return null + return null; } } } @@ -112,13 +112,13 @@ Item { acceptedButtons: Qt.LeftButton onClicked: mouse => { - const types = ["linear", "mirrored", "wave"] - const currentIndex = types.indexOf(currentVisualizerType) - const nextIndex = (currentIndex + 1) % types.length - const newType = types[nextIndex] + const types = ["linear", "mirrored", "wave"]; + const currentIndex = types.indexOf(currentVisualizerType); + const nextIndex = (currentIndex + 1) % types.length; + const newType = types[nextIndex]; // Update settings directly, maybe this should be a widget setting... - Settings.data.audio.visualizerType = newType + Settings.data.audio.visualizerType = newType; } } diff --git a/Modules/Bar/Widgets/Battery.qml b/Modules/Bar/Widgets/Battery.qml index 08488fe5..4a9ff0fc 100644 --- a/Modules/Bar/Widgets/Battery.qml +++ b/Modules/Bar/Widgets/Battery.qml @@ -1,12 +1,12 @@ import QtQuick +import QtQuick.Layouts import Quickshell import Quickshell.Services.UPower -import QtQuick.Layouts import qs.Commons -import qs.Services.UI -import qs.Services.Hardware -import qs.Widgets import qs.Modules.Bar.Extras +import qs.Services.Hardware +import qs.Services.UI +import qs.Widgets Item { id: root @@ -22,12 +22,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -53,13 +53,13 @@ Item { function maybeNotify(percent, charging) { // Only notify once we are a below threshold if (!charging && !root.hasNotifiedLowBattery && percent <= warningThreshold) { - root.hasNotifiedLowBattery = true + root.hasNotifiedLowBattery = true; ToastService.showWarning(I18n.tr("toast.battery.low"), I18n.tr("toast.battery.low-desc", { "percent": Math.round(percent) - })) + })); } else if (root.hasNotifiedLowBattery && (charging || percent > warningThreshold + 5)) { // Reset when charging starts or when battery recovers 5% above threshold - root.hasNotifiedLowBattery = false + root.hasNotifiedLowBattery = false; } } @@ -67,20 +67,20 @@ Item { Connections { target: UPower.displayDevice function onPercentageChanged() { - var currentPercent = UPower.displayDevice.percentage * 100 - var isCharging = UPower.displayDevice.state === UPowerDeviceState.Charging - root.maybeNotify(currentPercent, isCharging) + var currentPercent = UPower.displayDevice.percentage * 100; + var isCharging = UPower.displayDevice.state === UPowerDeviceState.Charging; + root.maybeNotify(currentPercent, isCharging); } function onStateChanged() { - var isCharging = UPower.displayDevice.state === UPowerDeviceState.Charging + var isCharging = UPower.displayDevice.state === UPowerDeviceState.Charging; // Reset notification flag when charging starts if (isCharging) { - root.hasNotifiedLowBattery = false + root.hasNotifiedLowBattery = false; } // Also re-evaluate maybeNotify, as state might have changed - var currentPercent = UPower.displayDevice.percentage * 100 - root.maybeNotify(currentPercent, isCharging) + var currentPercent = UPower.displayDevice.percentage * 100; + root.maybeNotify(currentPercent, isCharging); } } @@ -95,51 +95,50 @@ Item { autoHide: false forceOpen: isReady && (testMode || battery.isLaptopBattery) && displayMode === "alwaysShow" forceClose: displayMode === "alwaysHide" || !isReady || (!testMode && !battery.isLaptopBattery) - onClicked: PanelService.getPanel("batteryPanel", screen)?.toggle(this) tooltipText: { - let lines = [] + let lines = []; if (testMode) { - lines.push(`Time left: ${Time.formatVagueHumanReadableDuration(12345)}.`) - return lines.join("\n") + lines.push(`Time left: ${Time.formatVagueHumanReadableDuration(12345)}.`); + return lines.join("\n"); } if (!isReady || !battery.isLaptopBattery) { - return I18n.tr("battery.no-battery-detected") + return I18n.tr("battery.no-battery-detected"); } if (battery.timeToEmpty > 0) { lines.push(I18n.tr("battery.time-left", { "time": Time.formatVagueHumanReadableDuration(battery.timeToEmpty) - })) + })); } if (battery.timeToFull > 0) { lines.push(I18n.tr("battery.time-until-full", { "time": Time.formatVagueHumanReadableDuration(battery.timeToFull) - })) + })); } if (battery.changeRate !== undefined) { - const rate = battery.changeRate + const rate = battery.changeRate; if (rate > 0) { lines.push(charging ? I18n.tr("battery.charging-rate", { "rate": rate.toFixed(2) }) : I18n.tr("battery.discharging-rate", { "rate": rate.toFixed(2) - })) + })); } else if (rate < 0) { lines.push(I18n.tr("battery.discharging-rate", { "rate": Math.abs(rate).toFixed(2) - })) + })); } else { // Rate is 0 - check if plugged in (charging state) or idle - lines.push(charging ? I18n.tr("battery.plugged-in") : I18n.tr("battery.idle")) + lines.push(charging ? I18n.tr("battery.plugged-in") : I18n.tr("battery.idle")); } } else { - lines.push(charging ? I18n.tr("battery.charging") : I18n.tr("battery.discharging")) + lines.push(charging ? I18n.tr("battery.charging") : I18n.tr("battery.discharging")); } if (battery.healthPercentage !== undefined && battery.healthPercentage > 0) { lines.push(I18n.tr("battery.health", { "percent": Math.round(battery.healthPercentage) - })) + })); } - return lines.join("\n") + return lines.join("\n"); } } } diff --git a/Modules/Bar/Widgets/Bluetooth.qml b/Modules/Bar/Widgets/Bluetooth.qml index a6b5894b..cbe63515 100644 --- a/Modules/Bar/Widgets/Bluetooth.qml +++ b/Modules/Bar/Widgets/Bluetooth.qml @@ -19,12 +19,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -41,16 +41,16 @@ Item { icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off" text: { if (BluetoothService.connectedDevices && BluetoothService.connectedDevices.length > 0) { - const firstDevice = BluetoothService.connectedDevices[0] - return firstDevice.name || firstDevice.deviceName + const firstDevice = BluetoothService.connectedDevices[0]; + return firstDevice.name || firstDevice.deviceName; } - return "" + return ""; } suffix: { if (BluetoothService.connectedDevices && BluetoothService.connectedDevices.length > 1) { - return ` + ${BluetoothService.connectedDevices.length - 1}` + return ` + ${BluetoothService.connectedDevices.length - 1}`; } - return "" + return ""; } autoHide: false forceOpen: !isBarVertical && root.displayMode === "alwaysShow" @@ -59,9 +59,9 @@ Item { onRightClicked: BluetoothService.setBluetoothEnabled(!BluetoothService.enabled) tooltipText: { if (pill.text !== "") { - return pill.text + return pill.text; } - return I18n.tr("tooltips.bluetooth-devices") + return I18n.tr("tooltips.bluetooth-devices"); } } } diff --git a/Modules/Bar/Widgets/Brightness.qml b/Modules/Bar/Widgets/Brightness.qml index e426c4aa..98107aef 100644 --- a/Modules/Bar/Widgets/Brightness.qml +++ b/Modules/Bar/Widgets/Brightness.qml @@ -21,12 +21,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -40,13 +40,13 @@ Item { visible: getMonitor() !== null function getMonitor() { - return BrightnessService.getMonitorForScreen(screen) || null + return BrightnessService.getMonitorForScreen(screen) || null; } function getIcon() { - var monitor = getMonitor() - var brightness = monitor ? monitor.brightness : 0 - return brightness <= 0.5 ? "brightness-low" : "brightness-high" + var monitor = getMonitor(); + var brightness = monitor ? monitor.brightness : 0; + return brightness <= 0.5 ? "brightness-low" : "brightness-high"; } // Connection used to open the pill when brightness changes @@ -57,12 +57,12 @@ Item { // Ignore if this is the first time we receive an update. // Most likely service just kicked off. if (!firstBrightnessReceived) { - firstBrightnessReceived = true - return + firstBrightnessReceived = true; + return; } - pill.show() - hideTimerAfterChange.restart() + pill.show(); + hideTimerAfterChange.restart(); } } @@ -82,42 +82,42 @@ Item { icon: getIcon() autoHide: false // Important to be false so we can hover as long as we want text: { - var monitor = getMonitor() - return monitor ? Math.round(monitor.brightness * 100) : "" + var monitor = getMonitor(); + return monitor ? Math.round(monitor.brightness * 100) : ""; } suffix: text.length > 0 ? "%" : "-" forceOpen: displayMode === "alwaysShow" forceClose: displayMode === "alwaysHide" tooltipText: { - var monitor = getMonitor() + var monitor = getMonitor(); if (!monitor) - return "" + return ""; return I18n.tr("tooltips.brightness-at", { "brightness": Math.round(monitor.brightness * 100) - }) + }); } onWheel: function (angle) { - var monitor = getMonitor() + var monitor = getMonitor(); if (!monitor) - return + return; if (angle > 0) { - monitor.increaseBrightness() + monitor.increaseBrightness(); } else if (angle < 0) { - monitor.decreaseBrightness() + monitor.decreaseBrightness(); } } onClicked: { - var settingsPanel = PanelService.getPanel("settingsPanel", screen) - settingsPanel.requestedTab = SettingsPanel.Tab.Display - settingsPanel.open() + var settingsPanel = PanelService.getPanel("settingsPanel", screen); + settingsPanel.requestedTab = SettingsPanel.Tab.Display; + settingsPanel.open(); } onRightClicked: { - var settingsPanel = PanelService.getPanel("settingsPanel", screen) - settingsPanel.requestedTab = SettingsPanel.Tab.Display - settingsPanel.open() + var settingsPanel = PanelService.getPanel("settingsPanel", screen); + settingsPanel.requestedTab = SettingsPanel.Tab.Display; + settingsPanel.open(); } } } diff --git a/Modules/Bar/Widgets/Clock.qml b/Modules/Bar/Widgets/Clock.qml index 4eb93dba..19f6f754 100644 --- a/Modules/Bar/Widgets/Clock.qml +++ b/Modules/Bar/Widgets/Clock.qml @@ -20,12 +20,12 @@ Rectangle { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string barPosition: Settings.data.bar.position @@ -70,9 +70,9 @@ Rectangle { Binding on pointSize { value: { if (repeater.model.length == 1) { - return Style.fontSizeS * scaling + return Style.fontSizeS * scaling; } else { - return (index == 0) ? Style.fontSizeXS * scaling : Style.fontSizeXXS * scaling + return (index == 0) ? Style.fontSizeXS * scaling : Style.fontSizeXXS * scaling; } } } @@ -122,15 +122,15 @@ Rectangle { hoverEnabled: true onEntered: { if (!PanelService.getPanel("calendarPanel", screen)?.active) { - TooltipService.show(Screen, root, I18n.tr("clock.tooltip"), BarService.getTooltipDirection()) + TooltipService.show(Screen, root, I18n.tr("clock.tooltip"), BarService.getTooltipDirection()); } } onExited: { - TooltipService.hide() + TooltipService.hide(); } onClicked: { - TooltipService.hide() - PanelService.getPanel("calendarPanel", screen)?.toggle(this) + TooltipService.hide(); + PanelService.getPanel("calendarPanel", screen)?.toggle(this); } } } diff --git a/Modules/Bar/Widgets/ControlCenter.qml b/Modules/Bar/Widgets/ControlCenter.qml index 789bdeb7..8859b23e 100644 --- a/Modules/Bar/Widgets/ControlCenter.qml +++ b/Modules/Bar/Widgets/ControlCenter.qml @@ -1,11 +1,11 @@ import QtQuick +import QtQuick.Effects import Quickshell import Quickshell.Widgets -import QtQuick.Effects import qs.Commons -import qs.Widgets -import qs.Services.UI import qs.Services.System +import qs.Services.UI +import qs.Widgets NIconButton { id: root @@ -21,12 +21,12 @@ NIconButton { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string customIcon: widgetSettings.icon || widgetMetadata.icon @@ -34,8 +34,8 @@ NIconButton { readonly property string customIconPath: widgetSettings.customIconPath || "" readonly property bool colorizeDistroLogo: { if (widgetSettings.colorizeDistroLogo !== undefined) - return widgetSettings.colorizeDistroLogo - return widgetMetadata.colorizeDistroLogo !== undefined ? widgetMetadata.colorizeDistroLogo : false + return widgetSettings.colorizeDistroLogo; + return widgetMetadata.colorizeDistroLogo !== undefined ? widgetMetadata.colorizeDistroLogo : false; } // If we have a custom path or distro logo, don't use the theme icon. @@ -51,12 +51,12 @@ NIconButton { colorBorder: Color.transparent colorBorderHover: useDistroLogo ? Color.mHover : Color.transparent onClicked: { - var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen) + var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen); if (Settings.data.controlCenter.position === "close_to_bar_button") { // Willopen the panel next to the bar button. - controlCenterPanel?.toggle(this) + controlCenterPanel?.toggle(this); } else { - controlCenterPanel?.toggle() + controlCenterPanel?.toggle(); } } onRightClicked: PanelService.getPanel("settingsPanel", screen)?.toggle() @@ -69,10 +69,10 @@ NIconButton { height: width source: { if (customIconPath !== "") - return customIconPath.startsWith("file://") ? customIconPath : "file://" + customIconPath + return customIconPath.startsWith("file://") ? customIconPath : "file://" + customIconPath; if (useDistroLogo) - return HostService.osLogo - return "" + return HostService.osLogo; + return ""; } visible: source !== "" smooth: true diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 34aa3cbd..9cc000ba 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -3,10 +3,10 @@ import QtQuick.Layouts import Quickshell import Quickshell.Io import qs.Commons +import qs.Modules.Bar.Extras +import qs.Modules.Panels.Settings import qs.Services.UI import qs.Widgets -import qs.Modules.Panels.Settings -import qs.Modules.Bar.Extras Item { id: root @@ -22,12 +22,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -63,31 +63,31 @@ Item { autoHide: false forceOpen: _dynamicText !== "" tooltipText: { - var tooltipLines = [] + var tooltipLines = []; if (hasExec) { if (leftClickExec !== "") { - tooltipLines.push(`Left click: ${leftClickExec}.`) + tooltipLines.push(`Left click: ${leftClickExec}.`); } if (rightClickExec !== "") { - tooltipLines.push(`Right click: ${rightClickExec}.`) + tooltipLines.push(`Right click: ${rightClickExec}.`); } if (middleClickExec !== "") { - tooltipLines.push(`Middle click: ${middleClickExec}.`) + tooltipLines.push(`Middle click: ${middleClickExec}.`); } } if (_dynamicTooltip !== "") { if (tooltipLines.length > 0) { - tooltipLines.push("") + tooltipLines.push(""); } - tooltipLines.push(_dynamicTooltip) + tooltipLines.push(_dynamicTooltip); } if (tooltipLines.length === 0) { - return "Custom button, configure in settings." + return "Custom button, configure in settings."; } else { - return tooltipLines.join("\n") + return tooltipLines.join("\n"); } } @@ -135,121 +135,121 @@ Item { stderr: StdioCollector {} onExited: (exitCode, exitStatus) => { if (textStream) { - Logger.w("CustomButton", `Streaming text command exited (code: ${exitCode}), restarting...`) - return + Logger.w("CustomButton", `Streaming text command exited (code: ${exitCode}), restarting...`); + return; } } } function parseDynamicContent(content) { - var contentStr = String(content || "").trim() + var contentStr = String(content || "").trim(); if (parseJson) { - var lineToParse = contentStr + var lineToParse = contentStr; if (!textStream && contentStr.includes('\n')) { - const lines = contentStr.split('\n').filter(line => line.trim() !== '') + const lines = contentStr.split('\n').filter(line => line.trim() !== ''); if (lines.length > 0) { - lineToParse = lines[lines.length - 1] + lineToParse = lines[lines.length - 1]; } } try { - const parsed = JSON.parse(lineToParse) - const text = parsed.text || "" - const icon = parsed.icon || "" - const tooltip = parsed.tooltip || "" + const parsed = JSON.parse(lineToParse); + const text = parsed.text || ""; + const icon = parsed.icon || ""; + const tooltip = parsed.tooltip || ""; if (checkCollapse(text)) { - _dynamicText = "" - _dynamicIcon = "" - _dynamicTooltip = "" - return + _dynamicText = ""; + _dynamicIcon = ""; + _dynamicTooltip = ""; + return; } - _dynamicText = text - _dynamicIcon = icon - _dynamicTooltip = tooltip - return + _dynamicText = text; + _dynamicIcon = icon; + _dynamicTooltip = tooltip; + return; } catch (e) { - Logger.w("CustomButton", `Failed to parse JSON. Content: "${lineToParse}"`) + Logger.w("CustomButton", `Failed to parse JSON. Content: "${lineToParse}"`); } } if (checkCollapse(contentStr)) { - _dynamicText = "" - _dynamicIcon = "" - _dynamicTooltip = "" - return + _dynamicText = ""; + _dynamicIcon = ""; + _dynamicTooltip = ""; + return; } - _dynamicText = contentStr - _dynamicIcon = "" - _dynamicTooltip = "" + _dynamicText = contentStr; + _dynamicIcon = ""; + _dynamicTooltip = ""; } function checkCollapse(text) { if (!textCollapse || textCollapse.length === 0) { - return false + return false; } if (textCollapse.startsWith("/") && textCollapse.endsWith("/") && textCollapse.length > 1) { // Treat as regex - var pattern = textCollapse.substring(1, textCollapse.length - 1) + var pattern = textCollapse.substring(1, textCollapse.length - 1); try { - var regex = new RegExp(pattern) - return regex.test(text) + var regex = new RegExp(pattern); + return regex.test(text); } catch (e) { - Logger.w("CustomButton", `Invalid regex for textCollapse: ${textCollapse} - ${e.message}`) - return (textCollapse === text) // Fallback to exact match on invalid regex + Logger.w("CustomButton", `Invalid regex for textCollapse: ${textCollapse} - ${e.message}`); + return (textCollapse === text); // Fallback to exact match on invalid regex } } else { // Treat as plain string - return (textCollapse === text) + return (textCollapse === text); } } function onClicked() { if (leftClickExec) { - Quickshell.execDetached(["sh", "-c", leftClickExec]) - Logger.i("CustomButton", `Executing command: ${leftClickExec}`) + Quickshell.execDetached(["sh", "-c", leftClickExec]); + Logger.i("CustomButton", `Executing command: ${leftClickExec}`); } else if (!hasExec && !leftClickUpdateText) { // No script was defined, open settings - var settingsPanel = PanelService.getPanel("settingsPanel", screen) - settingsPanel.requestedTab = SettingsPanel.Tab.Bar - settingsPanel.open() + var settingsPanel = PanelService.getPanel("settingsPanel", screen); + settingsPanel.requestedTab = SettingsPanel.Tab.Bar; + settingsPanel.open(); } if (!textStream && leftClickUpdateText) { - runTextCommand() + runTextCommand(); } } function onRightClicked() { if (rightClickExec) { - Quickshell.execDetached(["sh", "-c", rightClickExec]) - Logger.i("CustomButton", `Executing command: ${rightClickExec}`) + Quickshell.execDetached(["sh", "-c", rightClickExec]); + Logger.i("CustomButton", `Executing command: ${rightClickExec}`); } if (!textStream && rightClickUpdateText) { - runTextCommand() + runTextCommand(); } } function onMiddleClicked() { if (middleClickExec) { - Quickshell.execDetached(["sh", "-c", middleClickExec]) - Logger.i("CustomButton", `Executing command: ${middleClickExec}`) + Quickshell.execDetached(["sh", "-c", middleClickExec]); + Logger.i("CustomButton", `Executing command: ${middleClickExec}`); } if (!textStream && middleClickUpdateText) { - runTextCommand() + runTextCommand(); } } function runTextCommand() { if (!textCommand || textCommand.length === 0) - return + return; if (textProc.running) - return - textProc.command = ["sh", "-lc", textCommand] - textProc.running = true + return; + textProc.command = ["sh", "-lc", textCommand]; + textProc.running = true; } } diff --git a/Modules/Bar/Widgets/DarkMode.qml b/Modules/Bar/Widgets/DarkMode.qml index 170b3f5f..79bd99f4 100644 --- a/Modules/Bar/Widgets/DarkMode.qml +++ b/Modules/Bar/Widgets/DarkMode.qml @@ -1,7 +1,7 @@ import Quickshell import qs.Commons -import qs.Widgets import qs.Services.UI +import qs.Widgets NIconButton { id: root diff --git a/Modules/Bar/Widgets/KeepAwake.qml b/Modules/Bar/Widgets/KeepAwake.qml index 6d065812..5611df2d 100644 --- a/Modules/Bar/Widgets/KeepAwake.qml +++ b/Modules/Bar/Widgets/KeepAwake.qml @@ -2,10 +2,10 @@ import QtQuick import QtQuick.Layouts import Quickshell import qs.Commons +import qs.Modules.Bar.Extras import qs.Services.Power import qs.Services.UI import qs.Widgets -import qs.Modules.Bar.Extras Item { id: root @@ -21,12 +21,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -47,20 +47,20 @@ Item { forceOpen: IdleInhibitorService.timeout !== null forceClose: IdleInhibitorService.timeout == null onWheel: function (delta) { - var sign = delta > 0 ? 1 : -1 + var sign = delta > 0 ? 1 : -1; // the offset makes scrolling down feel symmetrical to scrolling up - var timeout = IdleInhibitorService.timeout - (delta < 0 ? 60 : 0) + var timeout = IdleInhibitorService.timeout - (delta < 0 ? 60 : 0); if (timeout == null || timeout < 600) { - delta = 60 // <= 10m, increment at 1m interval + delta = 60; // <= 10m, increment at 1m interval } else if (timeout >= 600 && timeout < 1800) { - delta = 300 // >= 10m, increment at 5m interval + delta = 300; // >= 10m, increment at 5m interval } else if (timeout >= 1800 && timeout < 3600) { - delta = 600 // >= 30m, increment at 10m interval + delta = 600; // >= 30m, increment at 10m interval } else if (timeout >= 3600) { - delta = 1800 // > 1h, increment at 30m interval + delta = 1800; // > 1h, increment at 30m interval } - IdleInhibitorService.changeTimeout(delta * sign) + IdleInhibitorService.changeTimeout(delta * sign); } } } diff --git a/Modules/Bar/Widgets/KeyboardLayout.qml b/Modules/Bar/Widgets/KeyboardLayout.qml index e00fd2d6..17fec633 100644 --- a/Modules/Bar/Widgets/KeyboardLayout.qml +++ b/Modules/Bar/Widgets/KeyboardLayout.qml @@ -1,13 +1,13 @@ import QtQuick import QtQuick.Layouts import Quickshell -import Quickshell.Wayland import Quickshell.Io +import Quickshell.Wayland import qs.Commons -import qs.Services.UI -import qs.Services.Keyboard -import qs.Widgets import qs.Modules.Bar.Extras +import qs.Services.Keyboard +import qs.Services.UI +import qs.Widgets Item { id: root @@ -23,12 +23,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string displayMode: (widgetSettings.displayMode !== undefined) ? widgetSettings.displayMode : widgetMetadata.displayMode @@ -53,9 +53,9 @@ Item { }) forceOpen: root.displayMode === "forceOpen" forceClose: root.displayMode === "alwaysHide" - onClicked: { + onClicked: // You could open keyboard settings here if needed. - } + {} } } diff --git a/Modules/Bar/Widgets/LockKeys.qml b/Modules/Bar/Widgets/LockKeys.qml index a13dbd9b..834473f4 100644 --- a/Modules/Bar/Widgets/LockKeys.qml +++ b/Modules/Bar/Widgets/LockKeys.qml @@ -20,12 +20,12 @@ Rectangle { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string barPosition: Settings.data.bar.position diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 0867514d..01c6bfc0 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -2,11 +2,11 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell -import qs.Widgets.AudioSpectrum import qs.Commons import qs.Services.Media import qs.Services.UI import qs.Widgets +import qs.Widgets.AudioSpectrum Item { id: root @@ -23,12 +23,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isVerticalBar: (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") @@ -49,18 +49,18 @@ Item { readonly property string placeholderText: I18n.tr("bar.widget-settings.media-mini.no-active-player") readonly property string tooltipText: { - var title = getTitle() - var controls = "" + var title = getTitle(); + var controls = ""; if (MediaService.canGoNext) { - controls += "Right click for next.\n" + controls += "Right click for next.\n"; } if (MediaService.canGoPrevious) { - controls += "Middle click for previous." + controls += "Middle click for previous."; } if (controls !== "") { - return title + "\n\n" + controls + return title + "\n\n" + controls; } - return title + return title; } // Hide conditions @@ -94,57 +94,57 @@ Item { } function getTitle() { - return MediaService.trackTitle + (MediaService.trackArtist !== "" ? ` - ${MediaService.trackArtist}` : "") + return MediaService.trackTitle + (MediaService.trackArtist !== "" ? ` - ${MediaService.trackArtist}` : ""); } function calculatedVerticalDimension() { - return Math.round((Style.baseWidgetSize - 5) * scaling) + return Math.round((Style.baseWidgetSize - 5) * scaling); } function calculateContentWidth() { // Calculate the actual content width based on visible elements - var contentWidth = 0 - var margins = Style.marginS * scaling * 2 // Left and right margins + var contentWidth = 0; + var margins = Style.marginS * scaling * 2; // Left and right margins // Icon or album art width if (!hasActivePlayer || !showAlbumArt) { // Icon width - contentWidth += Math.round(18 * scaling) + contentWidth += Math.round(18 * scaling); } else if (showAlbumArt && hasActivePlayer) { // Album art width - contentWidth += 21 * scaling + contentWidth += 21 * scaling; } // Spacing between icon/art and text; only if there is text if (fullTitleMetrics.contentWidth > 0) { - contentWidth += Style.marginS * scaling + contentWidth += Style.marginS * scaling; // Text width (use the measured width) - contentWidth += fullTitleMetrics.contentWidth + contentWidth += fullTitleMetrics.contentWidth; // Additional small margin for text - contentWidth += Style.marginXXS * 2 + contentWidth += Style.marginXXS * 2; } // Add container margins - contentWidth += margins + contentWidth += margins; - return Math.ceil(contentWidth) + return Math.ceil(contentWidth); } // Dynamic width: adapt to content but respect maximum width setting readonly property real dynamicWidth: { // If using fixed width mode, always use maxWidth if (useFixedWidth) { - return maxWidth + return maxWidth; } // Otherwise, adapt to content if (!hasActivePlayer) { // Keep compact when no active player - return calculateContentWidth() + return calculateContentWidth(); } // Use content width but don't exceed user-set maximum width - return Math.min(calculateContentWidth(), maxWidth) + return Math.min(calculateContentWidth(), maxWidth); } // A hidden text element to safely measure the full title width @@ -279,11 +279,11 @@ Item { id: titleContainer Layout.preferredWidth: { // Calculate available width based on other elements in the row - var iconWidth = (windowIcon.visible ? (18 * scaling + Style.marginS * scaling) : 0) - var albumArtWidth = (hasActivePlayer && showAlbumArt ? (21 * scaling + Style.marginS * scaling) : 0) - var totalMargins = Style.marginXXS * 2 - var availableWidth = mainContainer.width - iconWidth - albumArtWidth - totalMargins - return Math.max(20, availableWidth) + var iconWidth = (windowIcon.visible ? (18 * scaling + Style.marginS * scaling) : 0); + var albumArtWidth = (hasActivePlayer && showAlbumArt ? (21 * scaling + Style.marginS * scaling) : 0); + var totalMargins = Style.marginXXS * 2; + var availableWidth = mainContainer.width - iconWidth - albumArtWidth - totalMargins; + return Math.max(20, availableWidth); } Layout.maximumWidth: Layout.preferredWidth Layout.alignment: Qt.AlignVCenter @@ -304,8 +304,8 @@ Item { repeat: false onTriggered: { if (scrollingMode === "always" && titleContainer.needsScrolling) { - titleContainer.isScrolling = true - titleContainer.isResetting = false + titleContainer.isScrolling = true; + titleContainer.isResetting = false; } } } @@ -313,48 +313,48 @@ Item { // Update scrolling state based on mode property var updateScrollingState: function () { if (scrollingMode === "never") { - isScrolling = false - isResetting = false + isScrolling = false; + isResetting = false; } else if (scrollingMode === "always") { if (needsScrolling) { if (mouseArea.containsMouse) { - isScrolling = false - isResetting = true + isScrolling = false; + isResetting = true; } else { - scrollStartTimer.restart() + scrollStartTimer.restart(); } } else { - scrollStartTimer.stop() - isScrolling = false - isResetting = false + scrollStartTimer.stop(); + isScrolling = false; + isResetting = false; } } else if (scrollingMode === "hover") { if (mouseArea.containsMouse && needsScrolling) { - isScrolling = true - isResetting = false + isScrolling = true; + isResetting = false; } else { - isScrolling = false + isScrolling = false; if (needsScrolling) { - isResetting = true + isResetting = true; } } } } onWidthChanged: { - containerWidth = width - updateScrollingState() + containerWidth = width; + updateScrollingState(); } Component.onCompleted: { - containerWidth = width - updateScrollingState() + containerWidth = width; + updateScrollingState(); } Connections { target: mouseArea function onContainsMouseChanged() { - titleContainer.updateScrollingState() + titleContainer.updateScrollingState(); } } @@ -380,11 +380,11 @@ Item { horizontalAlignment: hasActivePlayer ? Text.AlignLeft : Text.AlignHCenter color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant onTextChanged: { - titleContainer.isScrolling = false - titleContainer.isResetting = false - scrollContainer.scrollX = 0 + titleContainer.isScrolling = false; + titleContainer.isResetting = false; + scrollContainer.scrollX = 0; if (titleContainer.needsScrolling) { - scrollStartTimer.restart() + scrollStartTimer.restart(); } } } @@ -408,7 +408,7 @@ Item { duration: 300 easing.type: Easing.OutQuad onFinished: { - titleContainer.isResetting = false + titleContainer.isResetting = false; } } @@ -462,28 +462,28 @@ Item { acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton onClicked: mouse => { if (!hasActivePlayer || !MediaService.currentPlayer || !MediaService.canPlay) { - return + return; } if (mouse.button === Qt.LeftButton) { - MediaService.playPause() + MediaService.playPause(); } else if (mouse.button == Qt.RightButton) { - MediaService.next() - TooltipService.hide() + MediaService.next(); + TooltipService.hide(); } else if (mouse.button == Qt.MiddleButton) { - MediaService.previous() - TooltipService.hide() + MediaService.previous(); + TooltipService.hide(); } } onEntered: { - var textToShow = hasActivePlayer ? tooltipText : placeholderText + var textToShow = hasActivePlayer ? tooltipText : placeholderText; if ((textToShow !== "") && isVerticalBar || (scrollingMode === "never")) { - TooltipService.show(Screen, root, textToShow, BarService.getTooltipDirection()) + TooltipService.show(Screen, root, textToShow, BarService.getTooltipDirection()); } } onExited: { - TooltipService.hide() + TooltipService.hide(); } } } diff --git a/Modules/Bar/Widgets/Microphone.qml b/Modules/Bar/Widgets/Microphone.qml index 2c4ae1fe..56cf2169 100644 --- a/Modules/Bar/Widgets/Microphone.qml +++ b/Modules/Bar/Widgets/Microphone.qml @@ -23,12 +23,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -48,13 +48,13 @@ Item { // Logger.i("Bar:Microphone", "onInputVolumeChanged") if (!firstInputVolumeReceived) { // Ignore the first volume change - firstInputVolumeReceived = true + firstInputVolumeReceived = true; } else { // If a tooltip is visible while we show the pill // hide it so it doesn't overlap the volume slider. - TooltipService.hide() - pill.show() - externalHideTimer.restart() + TooltipService.hide(); + pill.show(); + externalHideTimer.restart(); } } } @@ -66,11 +66,11 @@ Item { // Logger.i("Bar:Microphone", "onInputMutedChanged") if (!firstInputVolumeReceived) { // Ignore the first mute change - firstInputVolumeReceived = true + firstInputVolumeReceived = true; } else { - TooltipService.hide() - pill.show() - externalHideTimer.restart() + TooltipService.hide(); + pill.show(); + externalHideTimer.restart(); } } } @@ -80,7 +80,7 @@ Item { running: false interval: 1500 onTriggered: { - pill.hide() + pill.hide(); } } @@ -101,25 +101,25 @@ Item { onWheel: function (delta) { // As soon as we start scrolling to adjust volume, hide the tooltip - TooltipService.hide() + TooltipService.hide(); - wheelAccumulator += delta + wheelAccumulator += delta; if (wheelAccumulator >= 120) { - wheelAccumulator = 0 - AudioService.setInputVolume(AudioService.inputVolume + AudioService.stepVolume) + wheelAccumulator = 0; + AudioService.setInputVolume(AudioService.inputVolume + AudioService.stepVolume); } else if (wheelAccumulator <= -120) { - wheelAccumulator = 0 - AudioService.setInputVolume(AudioService.inputVolume - AudioService.stepVolume) + wheelAccumulator = 0; + AudioService.setInputVolume(AudioService.inputVolume - AudioService.stepVolume); } } onClicked: { - PanelService.getPanel("audioPanel", screen)?.toggle(this) + PanelService.getPanel("audioPanel", screen)?.toggle(this); } onRightClicked: { - AudioService.setInputMuted(!AudioService.inputMuted) + AudioService.setInputMuted(!AudioService.inputMuted); } onMiddleClicked: { - Quickshell.execDetached(["pwvucontrol"]) + Quickshell.execDetached(["pwvucontrol"]); } } } diff --git a/Modules/Bar/Widgets/NightLight.qml b/Modules/Bar/Widgets/NightLight.qml index c04d713d..3d126784 100644 --- a/Modules/Bar/Widgets/NightLight.qml +++ b/Modules/Bar/Widgets/NightLight.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Wayland import qs.Commons @@ -28,24 +28,24 @@ NIconButton { onClicked: { // Check if wlsunset is available before enabling night light if (!ProgramCheckerService.wlsunsetAvailable) { - ToastService.showWarning(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.not-installed")) - return + ToastService.showWarning(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.not-installed")); + return; } if (!Settings.data.nightLight.enabled) { - Settings.data.nightLight.enabled = true - Settings.data.nightLight.forced = false + Settings.data.nightLight.enabled = true; + Settings.data.nightLight.forced = false; } else if (Settings.data.nightLight.enabled && !Settings.data.nightLight.forced) { - Settings.data.nightLight.forced = true + Settings.data.nightLight.forced = true; } else { - Settings.data.nightLight.enabled = false - Settings.data.nightLight.forced = false + Settings.data.nightLight.enabled = false; + Settings.data.nightLight.forced = false; } } onRightClicked: { - var settingsPanel = PanelService.getPanel("settingsPanel", screen) - settingsPanel.requestedTab = SettingsPanel.Tab.Display - settingsPanel.open() + var settingsPanel = PanelService.getPanel("settingsPanel", screen); + settingsPanel.requestedTab = SettingsPanel.Tab.Display; + settingsPanel.open(); } } diff --git a/Modules/Bar/Widgets/NoctaliaPerformance.qml b/Modules/Bar/Widgets/NoctaliaPerformance.qml index 4263604a..1cd2d033 100644 --- a/Modules/Bar/Widgets/NoctaliaPerformance.qml +++ b/Modules/Bar/Widgets/NoctaliaPerformance.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Wayland import qs.Commons @@ -26,6 +26,6 @@ NIconButton { tooltipText: PowerProfileService.noctaliaPerformanceMode ? I18n.tr("tooltips.noctalia-performance-enabled") : I18n.tr("tooltips.noctalia-performance-disabled") tooltipDirection: BarService.getTooltipDirection() onClicked: { - PowerProfileService.toggleNoctaliaPerformance() + PowerProfileService.toggleNoctaliaPerformance(); } } diff --git a/Modules/Bar/Widgets/NotificationHistory.qml b/Modules/Bar/Widgets/NotificationHistory.qml index 1dd21717..2c39d356 100644 --- a/Modules/Bar/Widgets/NotificationHistory.qml +++ b/Modules/Bar/Widgets/NotificationHistory.qml @@ -1,11 +1,11 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Wayland import qs.Commons -import qs.Services.UI import qs.Services.System +import qs.Services.UI import qs.Widgets NIconButton { @@ -22,27 +22,27 @@ NIconButton { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool showUnreadBadge: (widgetSettings.showUnreadBadge !== undefined) ? widgetSettings.showUnreadBadge : widgetMetadata.showUnreadBadge readonly property bool hideWhenZero: (widgetSettings.hideWhenZero !== undefined) ? widgetSettings.hideWhenZero : widgetMetadata.hideWhenZero function computeUnreadCount() { - var since = NotificationService.lastSeenTs - var count = 0 - var model = NotificationService.historyList + var since = NotificationService.lastSeenTs; + var count = 0; + var model = NotificationService.historyList; for (var i = 0; i < model.count; i++) { - var item = model.get(i) - var ts = item.timestamp instanceof Date ? item.timestamp.getTime() : item.timestamp + var item = model.get(i); + var ts = item.timestamp instanceof Date ? item.timestamp.getTime() : item.timestamp; if (ts > since) - count++ + count++; } - return count + return count; } baseSize: Style.capsuleHeight @@ -57,8 +57,8 @@ NIconButton { colorBorderHover: Color.transparent onClicked: { - var panel = PanelService.getPanel("notificationHistoryPanel", screen) - panel?.toggle(this) + var panel = PanelService.getPanel("notificationHistoryPanel", screen); + panel?.toggle(this); } onRightClicked: NotificationService.doNotDisturb = !NotificationService.doNotDisturb diff --git a/Modules/Bar/Widgets/ScreenRecorder.qml b/Modules/Bar/Widgets/ScreenRecorder.qml index 085db1e3..dcd05846 100644 --- a/Modules/Bar/Widgets/ScreenRecorder.qml +++ b/Modules/Bar/Widgets/ScreenRecorder.qml @@ -1,8 +1,8 @@ import Quickshell import qs.Commons -import qs.Services.UI import qs.Services.Media import qs.Services.System +import qs.Services.UI import qs.Widgets // Screen Recording Indicator @@ -24,10 +24,10 @@ NIconButton { function handleClick() { if (!ScreenRecorderService.isAvailable) { - ToastService.showError(I18n.tr("toast.recording.not-installed"), I18n.tr("toast.recording.not-installed-desc")) - return + ToastService.showError(I18n.tr("toast.recording.not-installed"), I18n.tr("toast.recording.not-installed-desc")); + return; } - ScreenRecorderService.toggleRecording() + ScreenRecorderService.toggleRecording(); } onClicked: handleClick() diff --git a/Modules/Bar/Widgets/SessionMenu.qml b/Modules/Bar/Widgets/SessionMenu.qml index 189504c8..d6971af5 100644 --- a/Modules/Bar/Widgets/SessionMenu.qml +++ b/Modules/Bar/Widgets/SessionMenu.qml @@ -19,12 +19,12 @@ NIconButton { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string colorName: widgetSettings.colorName !== undefined ? widgetSettings.colorName : widgetMetadata.colorName @@ -32,16 +32,16 @@ NIconButton { readonly property color iconColor: { switch (colorName) { case "primary": - return Color.mPrimary + return Color.mPrimary; case "secondary": - return Color.mSecondary + return Color.mSecondary; case "tertiary": - return Color.mTertiary + return Color.mTertiary; case "error": - return Color.mError + return Color.mError; case "onSurface": default: - return Color.mOnSurface + return Color.mOnSurface; } } diff --git a/Modules/Bar/Widgets/Spacer.qml b/Modules/Bar/Widgets/Spacer.qml index 92bc33f3..ce777902 100644 --- a/Modules/Bar/Widgets/Spacer.qml +++ b/Modules/Bar/Widgets/Spacer.qml @@ -19,12 +19,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } // Use settings or defaults from BarWidgetRegistry diff --git a/Modules/Bar/Widgets/SystemMonitor.qml b/Modules/Bar/Widgets/SystemMonitor.qml index e2f15fea..76444409 100644 --- a/Modules/Bar/Widgets/SystemMonitor.qml +++ b/Modules/Bar/Widgets/SystemMonitor.qml @@ -3,8 +3,8 @@ import QtQuick.Layouts import Quickshell import qs.Commons import qs.Modules.Panels.Settings -import qs.Services.UI import qs.Services.System +import qs.Services.UI import qs.Widgets Rectangle { @@ -21,12 +21,12 @@ Rectangle { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string barPosition: Settings.data.bar.position @@ -43,8 +43,8 @@ Rectangle { readonly property real iconSize: textSize * 1.4 readonly property real textSize: { - var base = isVertical ? width * 0.82 : height - return Math.max(1, (density === "compact") ? base * 0.43 : base * 0.33) + var base = isVertical ? width * 0.82 : height; + return Math.max(1, (density === "compact") ? base * 0.43 : base * 0.33); } // Match Workspace widget pill sizing: base ratio depends on bar density @@ -178,11 +178,11 @@ Rectangle { anchors.centerIn: parent onLoaded: { - item.warning = Qt.binding(() => cpuWarning) - item.critical = Qt.binding(() => cpuCritical) - item.indicatorWidth = Qt.binding(() => cpuUsageContainer.width) - item.warningColor = Qt.binding(() => root.warningColor) - item.criticalColor = Qt.binding(() => root.criticalColor) + item.warning = Qt.binding(() => cpuWarning); + item.critical = Qt.binding(() => cpuCritical); + item.indicatorWidth = Qt.binding(() => cpuUsageContainer.width); + item.warningColor = Qt.binding(() => root.warningColor); + item.criticalColor = Qt.binding(() => root.criticalColor); } } @@ -214,11 +214,11 @@ Rectangle { NText { text: { - let usage = Math.round(SystemStatService.cpuUsage) + let usage = Math.round(SystemStatService.cpuUsage); if (usage < 100) { - return `${usage}%` + return `${usage}%`; } else { - return usage + return usage; } } family: Settings.data.ui.fontFixed @@ -252,11 +252,11 @@ Rectangle { anchors.centerIn: parent onLoaded: { - item.warning = Qt.binding(() => tempWarning) - item.critical = Qt.binding(() => tempCritical) - item.indicatorWidth = Qt.binding(() => cpuTempContainer.width) - item.warningColor = Qt.binding(() => root.warningColor) - item.criticalColor = Qt.binding(() => root.criticalColor) + item.warning = Qt.binding(() => tempWarning); + item.critical = Qt.binding(() => tempCritical); + item.indicatorWidth = Qt.binding(() => cpuTempContainer.width); + item.warningColor = Qt.binding(() => root.warningColor); + item.criticalColor = Qt.binding(() => root.criticalColor); } } @@ -319,11 +319,11 @@ Rectangle { anchors.centerIn: parent onLoaded: { - item.warning = Qt.binding(() => memWarning) - item.critical = Qt.binding(() => memCritical) - item.indicatorWidth = Qt.binding(() => memoryContainer.width) - item.warningColor = Qt.binding(() => root.warningColor) - item.criticalColor = Qt.binding(() => root.criticalColor) + item.warning = Qt.binding(() => memWarning); + item.critical = Qt.binding(() => memCritical); + item.indicatorWidth = Qt.binding(() => memoryContainer.width); + item.warningColor = Qt.binding(() => root.warningColor); + item.criticalColor = Qt.binding(() => root.criticalColor); } } @@ -472,11 +472,11 @@ Rectangle { anchors.centerIn: parent onLoaded: { - item.warning = Qt.binding(() => diskWarning) - item.critical = Qt.binding(() => diskCritical) - item.indicatorWidth = Qt.binding(() => diskContainer.width) - item.warningColor = Qt.binding(() => root.warningColor) - item.criticalColor = Qt.binding(() => root.criticalColor) + item.warning = Qt.binding(() => diskWarning); + item.critical = Qt.binding(() => diskCritical); + item.indicatorWidth = Qt.binding(() => diskContainer.width); + item.warningColor = Qt.binding(() => root.warningColor); + item.criticalColor = Qt.binding(() => root.criticalColor); } } diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index 30b41e72..8891f64a 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -2,8 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell -import Quickshell.Widgets import Quickshell.Wayland +import Quickshell.Widgets import qs.Commons import qs.Services.Compositor import qs.Services.UI @@ -27,12 +27,12 @@ Rectangle { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } property bool hasWindow: false @@ -42,35 +42,35 @@ Rectangle { function updateHasWindow() { try { - var total = CompositorService.windows.count || 0 + var total = CompositorService.windows.count || 0; var activeIds = CompositorService.getActiveWorkspaces().map(function (ws) { - return ws.id - }) - var found = false + return ws.id; + }); + var found = false; for (var i = 0; i < total; i++) { - var w = CompositorService.windows.get(i) + var w = CompositorService.windows.get(i); if (!w) - continue - var passOutput = (!onlySameOutput) || (w.output == screen.name) - var passWorkspace = (!onlyActiveWorkspaces) || (activeIds.includes(w.workspaceId)) + continue; + var passOutput = (!onlySameOutput) || (w.output == screen.name); + var passWorkspace = (!onlyActiveWorkspaces) || (activeIds.includes(w.workspaceId)); if (passOutput && passWorkspace) { - found = true - break + found = true; + break; } } - hasWindow = found + hasWindow = found; } catch (e) { - hasWindow = false + hasWindow = false; } } Connections { target: CompositorService function onWindowListChanged() { - updateHasWindow() + updateHasWindow(); } function onWorkspaceChanged() { - updateHasWindow() + updateHasWindow(); } } @@ -117,7 +117,7 @@ Rectangle { property ShellScreen screen: root.screen visible: (!onlySameOutput || modelData.output == screen.name) && (!onlyActiveWorkspaces || CompositorService.getActiveWorkspaces().map(function (ws) { - return ws.id + return ws.id; }).includes(modelData.workspaceId)) Layout.preferredWidth: root.itemSize @@ -125,7 +125,6 @@ Rectangle { Layout.alignment: Qt.AlignCenter IconImage { - id: appIcon width: parent.width height: parent.height @@ -144,10 +143,10 @@ Rectangle { } Rectangle { + id: iconBackground anchors.bottomMargin: -2 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter - id: iconBackground width: 4 height: 4 color: modelData.isFocused ? Color.mPrimary : Color.transparent @@ -163,19 +162,18 @@ Rectangle { onPressed: function (mouse) { if (!taskbarItem.modelData) - return - + return; if (mouse.button === Qt.LeftButton) { try { - CompositorService.focusWindow(taskbarItem.modelData) + CompositorService.focusWindow(taskbarItem.modelData); } catch (error) { - Logger.e("Taskbar", "Failed to activate toplevel: " + error) + Logger.e("Taskbar", "Failed to activate toplevel: " + error); } } else if (mouse.button === Qt.RightButton) { try { - CompositorService.closeWindow(taskbarItem.modelData) + CompositorService.closeWindow(taskbarItem.modelData); } catch (error) { - Logger.e("Taskbar", "Failed to close toplevel: " + error) + Logger.e("Taskbar", "Failed to close toplevel: " + error); } } } diff --git a/Modules/Bar/Widgets/TaskbarGrouped.qml b/Modules/Bar/Widgets/TaskbarGrouped.qml index a57a69de..89beb15f 100644 --- a/Modules/Bar/Widgets/TaskbarGrouped.qml +++ b/Modules/Bar/Widgets/TaskbarGrouped.qml @@ -26,12 +26,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string labelMode: (widgetSettings.labelMode !== undefined) ? widgetSettings.labelMode : widgetMetadata.labelMode readonly property bool hideUnoccupied: (widgetSettings.hideUnoccupied !== undefined) ? widgetSettings.hideUnoccupied : widgetMetadata.hideUnoccupied @@ -48,40 +48,39 @@ Item { property bool wheelCooldown: false function refreshWorkspaces() { - localWorkspaces.clear() + localWorkspaces.clear(); if (!screen) - return - - const screenName = screen.name.toLowerCase() + return; + const screenName = screen.name.toLowerCase(); for (var i = 0; i < CompositorService.workspaces.count; i++) { - const ws = CompositorService.workspaces.get(i) + const ws = CompositorService.workspaces.get(i); if (ws.output.toLowerCase() !== screenName) - continue + continue; if (hideUnoccupied && !ws.isOccupied && !ws.isFocused) - continue + continue; // Copy all properties from ws and add windows - var workspaceData = Object.assign({}, ws) - workspaceData.windows = CompositorService.getWindowsForWorkspace(ws.id) + var workspaceData = Object.assign({}, ws); + workspaceData.windows = CompositorService.getWindowsForWorkspace(ws.id); - localWorkspaces.append(workspaceData) + localWorkspaces.append(workspaceData); } - updateWorkspaceFocus() + updateWorkspaceFocus(); } function triggerUnifiedWave() { - effectColor = Color.mPrimary - masterAnimation.restart() + effectColor = Color.mPrimary; + masterAnimation.restart(); } function updateWorkspaceFocus() { for (var i = 0; i < localWorkspaces.count; i++) { - const ws = localWorkspaces.get(i) + const ws = localWorkspaces.get(i); if (ws.isFocused === true) { - root.triggerUnifiedWave() - break + root.triggerUnifiedWave(); + break; } } } @@ -89,27 +88,27 @@ Item { function getFocusedLocalIndex() { for (var i = 0; i < localWorkspaces.count; i++) { if (localWorkspaces.get(i).isFocused === true) - return i + return i; } - return -1 + return -1; } function switchByOffset(offset) { if (localWorkspaces.count === 0) - return - var current = getFocusedLocalIndex() + return; + var current = getFocusedLocalIndex(); if (current < 0) - current = 0 - var next = (current + offset) % localWorkspaces.count + current = 0; + var next = (current + offset) % localWorkspaces.count; if (next < 0) - next = localWorkspaces.count - 1 - const ws = localWorkspaces.get(next) + next = localWorkspaces.count - 1; + const ws = localWorkspaces.get(next); if (ws && ws.idx !== undefined) - CompositorService.switchToWorkspace(ws) + CompositorService.switchToWorkspace(ws); } Component.onCompleted: { - refreshWorkspaces() + refreshWorkspaces(); } onScreenChanged: refreshWorkspaces() @@ -122,11 +121,11 @@ Item { target: CompositorService function onWorkspacesChanged() { - refreshWorkspaces() + refreshWorkspaces(); } function onWindowListChanged() { - refreshWorkspaces() + refreshWorkspaces(); } } @@ -163,8 +162,8 @@ Item { interval: 150 repeat: false onTriggered: { - root.wheelCooldown = false - root.wheelAccumulatedDelta = 0 + root.wheelCooldown = false; + root.wheelAccumulatedDelta = 0; } } @@ -175,24 +174,24 @@ Item { acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad onWheel: function (event) { if (root.wheelCooldown) - return + return; // Prefer vertical delta, fall back to horizontal if needed - var dy = event.angleDelta.y - var dx = event.angleDelta.x - var useDy = Math.abs(dy) >= Math.abs(dx) - var delta = useDy ? dy : dx + var dy = event.angleDelta.y; + var dx = event.angleDelta.x; + var useDy = Math.abs(dy) >= Math.abs(dx); + var delta = useDy ? dy : dx; // One notch is typically 120 - root.wheelAccumulatedDelta += delta - var step = 120 + root.wheelAccumulatedDelta += delta; + var step = 120; if (Math.abs(root.wheelAccumulatedDelta) >= step) { - var direction = root.wheelAccumulatedDelta > 0 ? -1 : 1 + var direction = root.wheelAccumulatedDelta > 0 ? -1 : 1; // For vertical layout, natural mapping: wheel up -> previous, down -> next (already handled by sign) // For horizontal layout, same mapping using vertical wheel - root.switchByOffset(direction) - root.wheelCooldown = true - wheelDebounce.restart() - root.wheelAccumulatedDelta = 0 - event.accepted = true + root.switchByOffset(direction); + root.wheelCooldown = true; + wheelDebounce.restart(); + root.wheelAccumulatedDelta = 0; + event.accepted = true; } } } @@ -220,7 +219,7 @@ Item { enabled: !hasWindows cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor onClicked: { - CompositorService.switchToWorkspace(workspaceModel) + CompositorService.switchToWorkspace(workspaceModel); } } @@ -296,22 +295,22 @@ Item { onPressed: function (mouse) { if (!model) { - return + return; } if (mouse.button === Qt.LeftButton) { - CompositorService.focusWindow(model) + CompositorService.focusWindow(model); } else if (mouse.button === Qt.RightButton) { - CompositorService.closeWindow(model) + CompositorService.closeWindow(model); } } onEntered: { - taskbarItem.itemHovered = true - TooltipService.show(Screen, taskbarItem, model.title || model.appId || "Unknown app.", BarService.getTooltipDirection()) + taskbarItem.itemHovered = true; + TooltipService.show(Screen, taskbarItem, model.title || model.appId || "Unknown app.", BarService.getTooltipDirection()); } onExited: { - taskbarItem.itemHovered = false - TooltipService.hide() + taskbarItem.itemHovered = false; + TooltipService.hide(); } } } @@ -341,13 +340,13 @@ Item { color: { if (workspaceModel.isFocused) - return Color.mPrimary + return Color.mPrimary; if (workspaceModel.isUrgent) - return Color.mError + return Color.mError; if (hasWindows) - return Color.mSecondary + return Color.mSecondary; - return Qt.alpha(Color.mOutline, 0.3) + return Qt.alpha(Color.mOutline, 0.3); } scale: workspaceModel.isActive ? 1.0 : 0.9 @@ -409,24 +408,24 @@ Item { color: { if (workspaceModel.isFocused) - return Color.mOnPrimary + return Color.mOnPrimary; if (workspaceModel.isUrgent) - return Color.mOnError + return Color.mOnError; if (hasWindows) - return Color.mOnSecondary + return Color.mOnSecondary; - return Color.mOnSurface + return Color.mOnSurface; } opacity: { if (workspaceModel.isFocused) - return 1.0 + return 1.0; if (workspaceModel.isUrgent) - return 0.9 + return 0.9; if (hasWindows) - return 0.8 + return 0.8; - return 0.6 + return 0.6; } Behavior on opacity { diff --git a/Modules/Bar/Widgets/Tray.qml b/Modules/Bar/Widgets/Tray.qml index 921a66c4..10a0da58 100644 --- a/Modules/Bar/Widgets/Tray.qml +++ b/Modules/Bar/Widgets/Tray.qml @@ -1,7 +1,7 @@ import QtQuick +import QtQuick.Controls import QtQuick.Effects import QtQuick.Layouts -import QtQuick.Controls import Quickshell import Quickshell.Services.SystemTray import Quickshell.Widgets @@ -21,8 +21,8 @@ Rectangle { // Get shared tray menu window from PanelService (reactive to trigger changes) readonly property var trayMenuWindow: { // Reference trigger to force re-evaluation - var _ = trayMenuUpdateTrigger - return PanelService.getTrayMenuWindow(screen) + var _ = trayMenuUpdateTrigger; + return PanelService.getTrayMenuWindow(screen); } readonly property var trayMenu: trayMenuWindow ? trayMenuWindow.trayMenuLoader : null @@ -31,7 +31,7 @@ Rectangle { target: PanelService function onTrayMenuWindowRegistered(registeredScreen) { if (registeredScreen === screen) { - root.trayMenuUpdateTrigger++ + root.trayMenuUpdateTrigger++; } } } @@ -45,12 +45,12 @@ Rectangle { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string barPosition: Settings.data.bar.position @@ -76,149 +76,149 @@ Rectangle { } function _performFilteredItemsUpdate() { - let newItems = [] + let newItems = []; if (SystemTray.items && SystemTray.items.values) { - const trayItems = SystemTray.items.values + const trayItems = SystemTray.items.values; for (var i = 0; i < trayItems.length; i++) { - const item = trayItems[i] + const item = trayItems[i]; if (!item) { - continue + continue; } - const title = item.tooltipTitle || item.name || item.id || "" + const title = item.tooltipTitle || item.name || item.id || ""; // Check if blacklisted - let isBlacklisted = false + let isBlacklisted = false; if (root.blacklist && root.blacklist.length > 0) { for (var j = 0; j < root.blacklist.length; j++) { - const rule = root.blacklist[j] + const rule = root.blacklist[j]; if (wildCardMatch(title, rule)) { - isBlacklisted = true - break + isBlacklisted = true; + break; } } } if (!isBlacklisted) { - newItems.push(item) + newItems.push(item); } } } // If drawer is disabled, show all items inline if (!root.drawerEnabled) { - filteredItems = newItems - dropdownItems = [] + filteredItems = newItems; + dropdownItems = []; } else { // Build inline (pinned) and drawer (unpinned) lists // If pinned list is empty, all items go to drawer (none inline) // If pinned list has items, pinned items are inline, rest go to drawer if (pinned && pinned.length > 0) { - let pinnedItems = [] + let pinnedItems = []; for (var k = 0; k < newItems.length; k++) { - const item2 = newItems[k] - const title2 = item2.tooltipTitle || item2.name || item2.id || "" + const item2 = newItems[k]; + const title2 = item2.tooltipTitle || item2.name || item2.id || ""; for (var m = 0; m < pinned.length; m++) { - const rule2 = pinned[m] + const rule2 = pinned[m]; if (wildCardMatch(title2, rule2)) { - pinnedItems.push(item2) - break + pinnedItems.push(item2); + break; } } } - filteredItems = pinnedItems + filteredItems = pinnedItems; // Unpinned items go to drawer - let unpinnedItems = [] + let unpinnedItems = []; for (var v = 0; v < newItems.length; v++) { - const cand = newItems[v] - let isPinned = false + const cand = newItems[v]; + let isPinned = false; for (var f = 0; f < filteredItems.length; f++) { if (filteredItems[f] === cand) { - isPinned = true - break + isPinned = true; + break; } } if (!isPinned) - unpinnedItems.push(cand) + unpinnedItems.push(cand); } - dropdownItems = unpinnedItems + dropdownItems = unpinnedItems; } else { // No pinned items: all items go to drawer (none inline) - filteredItems = [] - dropdownItems = newItems + filteredItems = []; + dropdownItems = newItems; } } } function updateFilteredItems() { - updateDebounceTimer.restart() + updateDebounceTimer.restart(); } function wildCardMatch(str, rule) { if (!str || !rule) { - return false + return false; } //Logger.d("Tray", "wildCardMatch - Input str:", str, "rule:", rule) // Escape all special regex characters in the rule - let escapedRule = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + let escapedRule = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Convert '*' to '.*' for wildcard matching - let pattern = escapedRule.replace(/\\\*/g, '.*') + let pattern = escapedRule.replace(/\\\*/g, '.*'); // Add ^ and $ to match the entire string - pattern = '^' + pattern + '$' + pattern = '^' + pattern + '$'; //Logger.d("Tray", "wildCardMatch - Generated pattern:", pattern) try { - const regex = new RegExp(pattern, 'i') + const regex = new RegExp(pattern, 'i'); // 'i' for case-insensitive //Logger.d("Tray", "wildCardMatch - Regex test result:", regex.test(str)) - return regex.test(str) + return regex.test(str); } catch (e) { - Logger.w("Tray", "Invalid regex pattern for wildcard match:", rule, e.message) - return false // If regex is invalid, it won't match + Logger.w("Tray", "Invalid regex pattern for wildcard match:", rule, e.message); + return false; // If regex is invalid, it won't match } } function toggleDrawer(button) { - TooltipService.hideImmediately() + TooltipService.hideImmediately(); // Close the tray menu if it's open if (trayMenuWindow && trayMenuWindow.visible) { - trayMenuWindow.close() + trayMenuWindow.close(); } - const panel = PanelService.getPanel("trayDrawerPanel", root.screen) + const panel = PanelService.getPanel("trayDrawerPanel", root.screen); if (panel) { - panel.widgetSection = root.section - panel.widgetIndex = root.sectionWidgetIndex - panel.toggle(this) + panel.widgetSection = root.section; + panel.widgetIndex = root.sectionWidgetIndex; + panel.toggle(this); } } function onLoaded() { // When the widget is fully initialized with its props set the screen for the trayMenu if (trayMenu && trayMenu.item) { - trayMenu.item.screen = screen + trayMenu.item.screen = screen; } } Connections { target: SystemTray.items function onValuesChanged() { - root.updateFilteredItems() + root.updateFilteredItems(); } } Connections { target: Settings function onSettingsSaved() { - root.updateFilteredItems() + root.updateFilteredItems(); } } Component.onCompleted: { - root.updateFilteredItems() // Initial update + root.updateFilteredItems(); // Initial update } visible: filteredItems.length > 0 || dropdownItems.length > 0 @@ -248,14 +248,14 @@ Rectangle { icon: { switch (barPosition) { case "bottom": - return "caret-up" + return "caret-up"; case "left": - return "caret-right" + return "caret-right"; case "right": - return "caret-left" + return "caret-left"; case "top": default: - return "caret-down" + return "caret-down"; } } onClicked: toggleDrawer(this) @@ -283,20 +283,20 @@ Rectangle { property bool menuJustOpened: false source: { - let icon = modelData?.icon || "" + let icon = modelData?.icon || ""; if (!icon) { - return "" + return ""; } // Process icon path if (icon.includes("?path=")) { - const chunks = icon.split("?path=") - const name = chunks[0] - const path = chunks[1] - const fileName = name.substring(name.lastIndexOf("/") + 1) - return `file://${path}/${fileName}` + const chunks = icon.split("?path="); + const name = chunks[0]; + const path = chunks[1]; + const fileName = name.substring(name.lastIndexOf("/") + 1); + return `file://${path}/${fileName}`; } - return icon + return icon; } opacity: status === Image.Ready ? 1 : 0 @@ -315,71 +315,71 @@ Rectangle { acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton onClicked: mouse => { if (!modelData) { - return + return; } if (mouse.button === Qt.LeftButton) { // Close any open menu first if (trayMenuWindow) { - trayMenuWindow.close() + trayMenuWindow.close(); } if (!modelData.onlyMenu) { - modelData.activate() + modelData.activate(); } } else if (mouse.button === Qt.MiddleButton) { // Close the menu if it was visible if (trayMenuWindow && trayMenuWindow.visible) { - trayMenuWindow.close() - return + trayMenuWindow.close(); + return; } - modelData.secondaryActivate && modelData.secondaryActivate() + modelData.secondaryActivate && modelData.secondaryActivate(); } else if (mouse.button === Qt.RightButton) { - TooltipService.hideImmediately() + TooltipService.hideImmediately(); // Close the menu if it was visible if (trayMenuWindow && trayMenuWindow.visible) { - trayMenuWindow.close() - return + trayMenuWindow.close(); + return; } // Close any opened panel if ((PanelService.openedPanel !== null) && !PanelService.openedPanel.isClosing) { - PanelService.openedPanel.close() + PanelService.openedPanel.close(); } if (modelData.hasMenu && modelData.menu && trayMenuWindow && trayMenu && trayMenu.item) { - trayMenuWindow.open() + trayMenuWindow.open(); // Position menu based on bar position - let menuX, menuY + let menuX, menuY; if (barPosition === "left") { // For left bar: position menu to the right of the bar - menuX = width + Style.marginM - menuY = 0 + menuX = width + Style.marginM; + menuY = 0; } else if (barPosition === "right") { // For right bar: position menu to the left of the bar - menuX = -trayMenu.item.width - Style.marginM - menuY = 0 + menuX = -trayMenu.item.width - Style.marginM; + menuY = 0; } else { // For horizontal bars: center horizontally and position below - menuX = (width / 2) - (trayMenu.item.width / 2) - menuY = (barPosition === "top") ? Style.barHeight : -Style.barHeight + menuX = (width / 2) - (trayMenu.item.width / 2); + menuY = (barPosition === "top") ? Style.barHeight : -Style.barHeight; } - trayMenu.item.trayItem = modelData - trayMenu.item.widgetSection = root.section - trayMenu.item.widgetIndex = root.sectionWidgetIndex - trayMenu.item.showAt(parent, menuX, menuY) + trayMenu.item.trayItem = modelData; + trayMenu.item.widgetSection = root.section; + trayMenu.item.widgetIndex = root.sectionWidgetIndex; + trayMenu.item.showAt(parent, menuX, menuY); } else { - Logger.d("Tray", "No menu available for", modelData.id, "or trayMenu not set") + Logger.d("Tray", "No menu available for", modelData.id, "or trayMenu not set"); } } } onEntered: { if (trayMenuWindow) { - trayMenuWindow.close() + trayMenuWindow.close(); } - TooltipService.show(Screen, trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection()) + TooltipService.show(Screen, trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection()); } onExited: TooltipService.hide() } @@ -403,14 +403,14 @@ Rectangle { icon: { switch (barPosition) { case "bottom": - return "caret-up" + return "caret-up"; case "left": - return "caret-right" + return "caret-right"; case "right": - return "caret-left" + return "caret-left"; case "top": default: - return "caret-down" + return "caret-down"; } } onClicked: toggleDrawer(this) diff --git a/Modules/Bar/Widgets/Volume.qml b/Modules/Bar/Widgets/Volume.qml index c43a3380..566e6159 100644 --- a/Modules/Bar/Widgets/Volume.qml +++ b/Modules/Bar/Widgets/Volume.qml @@ -5,8 +5,8 @@ import Quickshell.Services.Pipewire import qs.Commons import qs.Modules.Bar.Extras import qs.Modules.Panels.Settings -import qs.Services.UI import qs.Services.Media +import qs.Services.UI import qs.Widgets Item { @@ -23,12 +23,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -48,12 +48,12 @@ Item { // Logger.i("Bar:Volume", "onVolumeChanged") if (!firstVolumeReceived) { // Ignore the first volume change - firstVolumeReceived = true + firstVolumeReceived = true; } else { // Hide any tooltip while the pill is visible / being updated - TooltipService.hide() - pill.show() - externalHideTimer.restart() + TooltipService.hide(); + pill.show(); + externalHideTimer.restart(); } } } @@ -63,7 +63,7 @@ Item { running: false interval: 1500 onTriggered: { - pill.hide() + pill.hide(); } } @@ -84,25 +84,25 @@ Item { onWheel: function (delta) { // Hide tooltip as soon as the user starts scrolling to adjust volume - TooltipService.hide() + TooltipService.hide(); - wheelAccumulator += delta + wheelAccumulator += delta; if (wheelAccumulator >= 120) { - wheelAccumulator = 0 - AudioService.increaseVolume() + wheelAccumulator = 0; + AudioService.increaseVolume(); } else if (wheelAccumulator <= -120) { - wheelAccumulator = 0 - AudioService.decreaseVolume() + wheelAccumulator = 0; + AudioService.decreaseVolume(); } } onClicked: { - PanelService.getPanel("audioPanel", screen)?.toggle(this) + PanelService.getPanel("audioPanel", screen)?.toggle(this); } onRightClicked: { - AudioService.setOutputMuted(!AudioService.muted) + AudioService.setOutputMuted(!AudioService.muted); } onMiddleClicked: { - Quickshell.execDetached(["sh", "-c", "pwvucontrol || pavucontrol"]) + Quickshell.execDetached(["sh", "-c", "pwvucontrol || pavucontrol"]); } } } diff --git a/Modules/Bar/Widgets/WallpaperSelector.qml b/Modules/Bar/Widgets/WallpaperSelector.qml index eb23970f..1593cbc5 100644 --- a/Modules/Bar/Widgets/WallpaperSelector.qml +++ b/Modules/Bar/Widgets/WallpaperSelector.qml @@ -21,11 +21,11 @@ NIconButton { colorBorder: Color.transparent colorBorderHover: Color.transparent onClicked: { - var wallpaperPanel = PanelService.getPanel("wallpaperPanel", screen) + var wallpaperPanel = PanelService.getPanel("wallpaperPanel", screen); if (Settings.data.wallpaper.panelPosition === "follow_bar") { - wallpaperPanel?.toggle(this) + wallpaperPanel?.toggle(this); } else { - wallpaperPanel?.toggle() + wallpaperPanel?.toggle(); } } } diff --git a/Modules/Bar/Widgets/WiFi.qml b/Modules/Bar/Widgets/WiFi.qml index 2508b0ba..11d4d663 100644 --- a/Modules/Bar/Widgets/WiFi.qml +++ b/Modules/Bar/Widgets/WiFi.qml @@ -1,9 +1,9 @@ import QtQuick import Quickshell import qs.Commons +import qs.Modules.Bar.Extras import qs.Services.Networking import qs.Services.UI -import qs.Modules.Bar.Extras Item { id: root @@ -19,12 +19,12 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property bool isBarVertical: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" @@ -41,37 +41,37 @@ Item { icon: { try { if (NetworkService.ethernetConnected) { - return NetworkService.internetConnectivity ? "ethernet" : "ethernet-off" + return NetworkService.internetConnectivity ? "ethernet" : "ethernet-off"; } - let connected = false - let signalStrength = 0 + let connected = false; + let signalStrength = 0; for (const net in NetworkService.networks) { if (NetworkService.networks[net].connected) { - connected = true - signalStrength = NetworkService.networks[net].signal - break + connected = true; + signalStrength = NetworkService.networks[net].signal; + break; } } - return connected ? NetworkService.signalIcon(signalStrength, true) : "wifi-off" + return connected ? NetworkService.signalIcon(signalStrength, true) : "wifi-off"; } catch (error) { - Logger.e("Wi-Fi", "Error getting icon:", error) - return "wifi-off" + Logger.e("Wi-Fi", "Error getting icon:", error); + return "wifi-off"; } } text: { try { if (NetworkService.ethernetConnected) { - return "" + return ""; } for (const net in NetworkService.networks) { if (NetworkService.networks[net].connected) { - return net + return net; } } - return "" + return ""; } catch (error) { - Logger.e("Wi-Fi", "Error getting ssid:", error) - return "error" + Logger.e("Wi-Fi", "Error getting ssid:", error); + return "error"; } } autoHide: false @@ -81,9 +81,9 @@ Item { onRightClicked: NetworkService.setWifiEnabled(!Settings.data.network.wifiEnabled) tooltipText: { if (pill.text !== "") { - return pill.text + return pill.text; } - return I18n.tr("tooltips.manage-wifi") + return I18n.tr("tooltips.manage-wifi"); } } } diff --git a/Modules/Bar/Widgets/Workspace.qml b/Modules/Bar/Widgets/Workspace.qml index f30af56f..4df0018d 100644 --- a/Modules/Bar/Widgets/Workspace.qml +++ b/Modules/Bar/Widgets/Workspace.qml @@ -1,8 +1,8 @@ import QtQuick import QtQuick.Controls +import QtQuick.Effects import QtQuick.Layouts import QtQuick.Window -import QtQuick.Effects import Quickshell import Quickshell.Io import qs.Commons @@ -24,23 +24,23 @@ Item { property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { - var widgets = Settings.data.bar.widgets[section] + var widgets = Settings.data.bar.widgets[section]; if (widgets && sectionWidgetIndex < widgets.length) { - return widgets[sectionWidgetIndex] + return widgets[sectionWidgetIndex]; } } - return {} + return {}; } readonly property string barPosition: Settings.data.bar.position readonly property bool isVertical: barPosition === "left" || barPosition === "right" readonly property bool density: Settings.data.bar.density readonly property real baseDimensionRatio: { - const b = (density === "compact") ? 0.85 : 0.65 + const b = (density === "compact") ? 0.85 : 0.65; if (widgetSettings.labelMode === "none") { - return b * 0.75 + return b * 0.75; } - return b + return b; } readonly property string labelMode: (widgetSettings.labelMode !== undefined) ? widgetSettings.labelMode : widgetMetadata.labelMode @@ -68,76 +68,76 @@ Item { implicitHeight: isVertical ? computeHeight() : Style.barHeight function getWorkspaceWidth(ws) { - const d = Style.capsuleHeight * root.baseDimensionRatio - const factor = ws.isActive ? 2.2 : 1 + const d = Style.capsuleHeight * root.baseDimensionRatio; + const factor = ws.isActive ? 2.2 : 1; // For name mode, calculate width based on actual text content if (labelMode === "name" && ws.name && ws.name.length > 0) { - const displayText = ws.name.substring(0, characterCount) - const textWidth = displayText.length * (d * 0.4) // Approximate width per character - const padding = d * 0.6 // Padding on both sides - return Math.max(d * factor, textWidth + padding) + const displayText = ws.name.substring(0, characterCount); + const textWidth = displayText.length * (d * 0.4); // Approximate width per character + const padding = d * 0.6; // Padding on both sides + return Math.max(d * factor, textWidth + padding); } - return d * factor + return d * factor; } function getWorkspaceHeight(ws) { - const d = Style.capsuleHeight * root.baseDimensionRatio - const factor = ws.isActive ? 2.2 : 1 - return d * factor + const d = Style.capsuleHeight * root.baseDimensionRatio; + const factor = ws.isActive ? 2.2 : 1; + return d * factor; } function computeWidth() { - let total = 0 + let total = 0; for (var i = 0; i < localWorkspaces.count; i++) { - const ws = localWorkspaces.get(i) - total += getWorkspaceWidth(ws) + const ws = localWorkspaces.get(i); + total += getWorkspaceWidth(ws); } - total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills - total += horizontalPadding * 2 - return Math.round(total) + total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills; + total += horizontalPadding * 2; + return Math.round(total); } function computeHeight() { - let total = 0 + let total = 0; for (var i = 0; i < localWorkspaces.count; i++) { - const ws = localWorkspaces.get(i) - total += getWorkspaceHeight(ws) + const ws = localWorkspaces.get(i); + total += getWorkspaceHeight(ws); } - total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills - total += horizontalPadding * 2 - return Math.round(total) + total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills; + total += horizontalPadding * 2; + return Math.round(total); } function getFocusedLocalIndex() { for (var i = 0; i < localWorkspaces.count; i++) { if (localWorkspaces.get(i).isFocused === true) - return i + return i; } - return -1 + return -1; } function switchByOffset(offset) { if (localWorkspaces.count === 0) - return - var current = getFocusedLocalIndex() + return; + var current = getFocusedLocalIndex(); if (current < 0) - current = 0 - var next = (current + offset) % localWorkspaces.count + current = 0; + var next = (current + offset) % localWorkspaces.count; if (next < 0) - next = localWorkspaces.count - 1 - const ws = localWorkspaces.get(next) + next = localWorkspaces.count - 1; + const ws = localWorkspaces.get(next); if (ws && ws.idx !== undefined) - CompositorService.switchToWorkspace(ws) + CompositorService.switchToWorkspace(ws); } Component.onCompleted: { - refreshWorkspaces() + refreshWorkspaces(); } Component.onDestruction: { - root.isDestroying = true + root.isDestroying = true; } onScreenChanged: refreshWorkspaces() @@ -146,40 +146,40 @@ Item { Connections { target: CompositorService function onWorkspacesChanged() { - refreshWorkspaces() + refreshWorkspaces(); } } function refreshWorkspaces() { - localWorkspaces.clear() + localWorkspaces.clear(); if (screen !== null) { for (var i = 0; i < CompositorService.workspaces.count; i++) { - const ws = CompositorService.workspaces.get(i) + const ws = CompositorService.workspaces.get(i); if (ws.output.toLowerCase() === screen.name.toLowerCase()) { if (hideUnoccupied && !ws.isOccupied && !ws.isFocused) { - continue + continue; } - localWorkspaces.append(ws) + localWorkspaces.append(ws); } } } - workspaceRepeaterHorizontal.model = localWorkspaces - workspaceRepeaterVertical.model = localWorkspaces - updateWorkspaceFocus() + workspaceRepeaterHorizontal.model = localWorkspaces; + workspaceRepeaterVertical.model = localWorkspaces; + updateWorkspaceFocus(); } function triggerUnifiedWave() { - effectColor = Color.mPrimary - masterAnimation.restart() + effectColor = Color.mPrimary; + masterAnimation.restart(); } function updateWorkspaceFocus() { for (var i = 0; i < localWorkspaces.count; i++) { - const ws = localWorkspaces.get(i) + const ws = localWorkspaces.get(i); if (ws.isFocused === true) { - root.triggerUnifiedWave() - root.workspaceChanged(ws.id, Color.mPrimary) - break + root.triggerUnifiedWave(); + root.workspaceChanged(ws.id, Color.mPrimary); + break; } } } @@ -228,8 +228,8 @@ Item { interval: 150 repeat: false onTriggered: { - root.wheelCooldown = false - root.wheelAccumulatedDelta = 0 + root.wheelCooldown = false; + root.wheelAccumulatedDelta = 0; } } @@ -240,24 +240,24 @@ Item { acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad onWheel: function (event) { if (root.wheelCooldown) - return + return; // Prefer vertical delta, fall back to horizontal if needed - var dy = event.angleDelta.y - var dx = event.angleDelta.x - var useDy = Math.abs(dy) >= Math.abs(dx) - var delta = useDy ? dy : dx + var dy = event.angleDelta.y; + var dx = event.angleDelta.x; + var useDy = Math.abs(dy) >= Math.abs(dx); + var delta = useDy ? dy : dx; // One notch is typically 120 - root.wheelAccumulatedDelta += delta - var step = 120 + root.wheelAccumulatedDelta += delta; + var step = 120; if (Math.abs(root.wheelAccumulatedDelta) >= step) { - var direction = root.wheelAccumulatedDelta > 0 ? -1 : 1 + var direction = root.wheelAccumulatedDelta > 0 ? -1 : 1; // For vertical layout, natural mapping: wheel up -> previous, down -> next (already handled by sign) // For horizontal layout, same mapping using vertical wheel - root.switchByOffset(direction) - root.wheelCooldown = true - wheelDebounce.restart() - root.wheelAccumulatedDelta = 0 - event.accepted = true + root.switchByOffset(direction); + root.wheelCooldown = true; + wheelDebounce.restart(); + root.wheelAccumulatedDelta = 0; + event.accepted = true; } } } @@ -290,9 +290,9 @@ Item { y: (pill.height - height) / 2 + (height - contentHeight) / 2 text: { if (labelMode === "name" && model.name && model.name.length > 0) { - return model.name.substring(0, characterCount) + return model.name.substring(0, characterCount); } else { - return model.idx.toString() + return model.idx.toString(); } } family: Settings.data.ui.fontFixed @@ -303,13 +303,13 @@ Item { wrapMode: Text.Wrap color: { if (model.isFocused) - return Color.mOnPrimary + return Color.mOnPrimary; if (model.isUrgent) - return Color.mOnError + return Color.mOnError; if (model.isOccupied) - return Color.mOnSecondary + return Color.mOnSecondary; - return Color.mOnSecondary + return Color.mOnSecondary; } } } @@ -318,13 +318,13 @@ Item { radius: width * 0.5 color: { if (model.isFocused) - return Color.mPrimary + return Color.mPrimary; if (model.isUrgent) - return Color.mError + return Color.mError; if (model.isOccupied) - return Color.mSecondary + return Color.mSecondary; - return Qt.alpha(Color.mSecondary, 0.3) + return Qt.alpha(Color.mSecondary, 0.3); } scale: model.isActive ? 1.0 : 0.9 z: 0 @@ -334,7 +334,7 @@ Item { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - CompositorService.switchToWorkspace(model) + CompositorService.switchToWorkspace(model); } hoverEnabled: true } @@ -435,9 +435,9 @@ Item { y: (pillVertical.height - height) / 2 + (height - contentHeight) / 2 text: { if (labelMode === "name" && model.name && model.name.length > 0) { - return model.name.substring(0, characterCount) + return model.name.substring(0, characterCount); } else { - return model.idx.toString() + return model.idx.toString(); } } family: Settings.data.ui.fontFixed @@ -448,13 +448,13 @@ Item { wrapMode: Text.Wrap color: { if (model.isFocused) - return Color.mOnPrimary + return Color.mOnPrimary; if (model.isUrgent) - return Color.mOnError + return Color.mOnError; if (model.isOccupied) - return Color.mOnSecondary + return Color.mOnSecondary; - return Color.mOnSurface + return Color.mOnSurface; } } } @@ -463,13 +463,13 @@ Item { radius: width * 0.5 color: { if (model.isFocused) - return Color.mPrimary + return Color.mPrimary; if (model.isUrgent) - return Color.mError + return Color.mError; if (model.isOccupied) - return Color.mSecondary + return Color.mSecondary; - return Color.mOutline + return Color.mOutline; } scale: model.isActive ? 1.0 : 0.9 z: 0 @@ -479,7 +479,7 @@ Item { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - CompositorService.switchToWorkspace(model) + CompositorService.switchToWorkspace(model); } hoverEnabled: true } diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index fc6c1614..f56c6816 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -1,7 +1,7 @@ import QtQuick import QtQuick.Controls -import QtQuick.Layouts import QtQuick.Effects +import QtQuick.Layouts import Quickshell import Quickshell.Wayland import Quickshell.Widgets @@ -26,7 +26,7 @@ Loader { target: BarService function onBarReadyChanged(screenName) { if (screenName === modelData.name) { - barIsReady = true + barIsReady = true; } } } @@ -35,7 +35,7 @@ Loader { Connections { target: ToplevelManager ? ToplevelManager.toplevels : null function onValuesChanged() { - updateDockApps() + updateDockApps(); } } @@ -43,17 +43,17 @@ Loader { Connections { target: Settings.data.dock function onPinnedAppsChanged() { - updateDockApps() + updateDockApps(); } function onOnlySameOutputChanged() { - updateDockApps() + updateDockApps(); } } // Initial update when component is ready Component.onCompleted: { if (ToplevelManager) { - updateDockApps() + updateDockApps(); } } @@ -93,33 +93,33 @@ Loader { // Function to close any open context menu function closeAllContextMenus() { if (currentContextMenu && currentContextMenu.visible) { - currentContextMenu.hide() + currentContextMenu.hide(); } } // Function to update the combined dock apps model function updateDockApps() { - const runningApps = ToplevelManager ? (ToplevelManager.toplevels.values || []) : [] - const pinnedApps = Settings.data.dock.pinnedApps || [] - const combined = [] - const processedAppIds = new Set() + const runningApps = ToplevelManager ? (ToplevelManager.toplevels.values || []) : []; + const pinnedApps = Settings.data.dock.pinnedApps || []; + const combined = []; + const processedAppIds = new Set(); // Strategy: Maintain app positions as much as possible // 1. First pass: Add all running apps (both pinned and non-pinned) in their current order runningApps.forEach(toplevel => { if (toplevel && toplevel.appId && !(Settings.data.dock.onlySameOutput && toplevel.screens && !toplevel.screens.includes(modelData))) { - const isPinned = pinnedApps.includes(toplevel.appId) - const appType = isPinned ? "pinned-running" : "running" + const isPinned = pinnedApps.includes(toplevel.appId); + const appType = isPinned ? "pinned-running" : "running"; combined.push({ "type": appType, "toplevel": toplevel, "appId": toplevel.appId, "title": toplevel.title - }) - processedAppIds.add(toplevel.appId) + }); + processedAppIds.add(toplevel.appId); } - }) + }); // 2. Second pass: Add non-running pinned apps at the end pinnedApps.forEach(pinnedAppId => { @@ -130,11 +130,11 @@ Loader { "toplevel": null, "appId": pinnedAppId, "title": pinnedAppId - }) + }); } - }) + }); - dockApps = combined + dockApps = combined; } // Timer to unload dock after hide animation completes @@ -143,7 +143,7 @@ Loader { interval: hideAnimationDuration + 50 // Add small buffer onTriggered: { if (hidden && autoHide) { - dockLoaded = false + dockLoaded = false; } } } @@ -155,14 +155,14 @@ Loader { onTriggered: { // Force menuHovered to false if no menu is current or visible if (!root.currentContextMenu || !root.currentContextMenu.visible) { - menuHovered = false + menuHovered = false; } if (autoHide && !dockHovered && !anyAppHovered && !peekHovered && !menuHovered) { - hidden = true - unloadTimer.restart() // Start unload timer when hiding + hidden = true; + unloadTimer.restart(); // Start unload timer when hiding } else if (autoHide && !dockHovered && !peekHovered) { // Restart timer if menu is closing (handles race condition) - restart() + restart(); } } } @@ -173,9 +173,9 @@ Loader { interval: showDelay onTriggered: { if (autoHide) { - dockLoaded = true // Load dock immediately - hidden = false // Then trigger show animation - unloadTimer.stop() // Cancel any pending unload + dockLoaded = true; // Load dock immediately + hidden = false; // Then trigger show animation + unloadTimer.stop(); // Cancel any pending unload } } } @@ -183,14 +183,14 @@ Loader { // Watch for autoHide setting changes onAutoHideChanged: { if (!autoHide) { - hidden = false - dockLoaded = true - hideTimer.stop() - showTimer.stop() - unloadTimer.stop() + hidden = false; + dockLoaded = true; + hideTimer.stop(); + showTimer.stop(); + unloadTimer.stop(); } else { - hidden = true - unloadTimer.restart() // Schedule unload after animation + hidden = true; + unloadTimer.restart(); // Schedule unload after animation } } @@ -218,16 +218,16 @@ Loader { hoverEnabled: true onEntered: { - peekHovered = true + peekHovered = true; if (hidden) { - showTimer.start() + showTimer.start(); } } onExited: { - peekHovered = false + peekHovered = false; if (!hidden && !dockHovered && !anyAppHovered && !menuHovered) { - hideTimer.restart() + hideTimer.restart(); } } } @@ -260,9 +260,9 @@ Loader { margins.bottom: { switch (Settings.data.bar.position) { case "bottom": - return (Style.barHeight + Style.marginM) + (Settings.data.bar.floating ? Settings.data.bar.marginVertical * Style.marginXL + floatingMargin : floatingMargin) + return (Style.barHeight + Style.marginM) + (Settings.data.bar.floating ? Settings.data.bar.marginVertical * Style.marginXL + floatingMargin : floatingMargin); default: - return floatingMargin + return floatingMargin; } } @@ -313,24 +313,24 @@ Loader { hoverEnabled: true onEntered: { - dockHovered = true + dockHovered = true; if (autoHide) { - showTimer.stop() - hideTimer.stop() - unloadTimer.stop() // Cancel unload if hovering + showTimer.stop(); + hideTimer.stop(); + unloadTimer.stop(); // Cancel unload if hovering } } onExited: { - dockHovered = false + dockHovered = false; if (autoHide && !anyAppHovered && !peekHovered && !menuHovered) { - hideTimer.restart() + hideTimer.restart(); } } onClicked: { // Close any open context menu when clicking on the dock background - closeAllContextMenus() + closeAllContextMenus(); } } @@ -342,8 +342,8 @@ Loader { function getAppIcon(appData): string { if (!appData || !appData.appId) - return "" - return ThemeIcons.iconForAppId(appData.appId?.toLowerCase()) + return ""; + return ThemeIcons.iconForAppId(appData.appId?.toLowerCase()); } RowLayout { @@ -371,7 +371,7 @@ Loader { Connections { target: modelData?.toplevel function onClosed() { - Qt.callLater(root.updateDockApps) + Qt.callLater(root.updateDockApps); } } @@ -452,9 +452,9 @@ Loader { onHoveredChanged: { // Only update menuHovered if this menu is current and visible if (root.currentContextMenu === contextMenu && contextMenu.visible) { - menuHovered = hovered + menuHovered = hovered; } else { - menuHovered = false + menuHovered = false; } } @@ -462,26 +462,26 @@ Loader { target: contextMenu function onRequestClose() { // Clear current menu immediately to prevent hover updates - root.currentContextMenu = null - hideTimer.stop() - contextMenu.hide() - menuHovered = false - anyAppHovered = false + root.currentContextMenu = null; + hideTimer.stop(); + contextMenu.hide(); + menuHovered = false; + anyAppHovered = false; } } onAppClosed: root.updateDockApps // Force immediate dock update when app is closed onVisibleChanged: { if (visible) { - root.currentContextMenu = contextMenu - anyAppHovered = false + root.currentContextMenu = contextMenu; + anyAppHovered = false; } else if (root.currentContextMenu === contextMenu) { - root.currentContextMenu = null - hideTimer.stop() - menuHovered = false - anyAppHovered = false + root.currentContextMenu = null; + hideTimer.stop(); + menuHovered = false; + anyAppHovered = false; // Restart hide timer after menu closes if (autoHide && !dockHovered && !anyAppHovered && !peekHovered && !menuHovered) { - hideTimer.restart() + hideTimer.restart(); } } } @@ -496,28 +496,28 @@ Loader { acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton onEntered: { - anyAppHovered = true - const appName = appButton.appTitle || appButton.appId || "Unknown" - const tooltipText = appName.length > 40 ? appName.substring(0, 37) + "..." : appName + anyAppHovered = true; + const appName = appButton.appTitle || appButton.appId || "Unknown"; + const tooltipText = appName.length > 40 ? appName.substring(0, 37) + "..." : appName; if (!contextMenu.visible) { - TooltipService.show(Screen, appButton, tooltipText, "top") + TooltipService.show(Screen, appButton, tooltipText, "top"); } if (autoHide) { - showTimer.stop() - hideTimer.stop() - unloadTimer.stop() // Cancel unload if hovering app + showTimer.stop(); + hideTimer.stop(); + unloadTimer.stop(); // Cancel unload if hovering app } } onExited: { - anyAppHovered = false - TooltipService.hide() + anyAppHovered = false; + TooltipService.hide(); // Clear menuHovered if no current menu or menu not visible if (!root.currentContextMenu || !root.currentContextMenu.visible) { - menuHovered = false + menuHovered = false; } if (autoHide && !dockHovered && !peekHovered && !menuHovered) { - hideTimer.restart() + hideTimer.restart(); } } @@ -525,33 +525,33 @@ Loader { if (mouse.button === Qt.RightButton) { // If right-clicking on the same app with an open context menu, close it if (root.currentContextMenu === contextMenu && contextMenu.visible) { - root.closeAllContextMenus() - return + root.closeAllContextMenus(); + return; } // Close any other existing context menu first - root.closeAllContextMenus() + root.closeAllContextMenus(); // Hide tooltip when showing context menu - TooltipService.hideImmediately() - contextMenu.show(appButton, modelData.toplevel || modelData) - return + TooltipService.hideImmediately(); + contextMenu.show(appButton, modelData.toplevel || modelData); + return; } // Close any existing context menu for non-right-click actions - root.closeAllContextMenus() + root.closeAllContextMenus(); // Check if toplevel is still valid (not a stale reference) - const isValidToplevel = modelData?.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(modelData.toplevel) + const isValidToplevel = modelData?.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(modelData.toplevel); if (mouse.button === Qt.MiddleButton && isValidToplevel && modelData.toplevel.close) { - modelData.toplevel.close() - Qt.callLater(root.updateDockApps) // Force immediate dock update + modelData.toplevel.close(); + Qt.callLater(root.updateDockApps); // Force immediate dock update } else if (mouse.button === Qt.LeftButton) { if (isValidToplevel && modelData.toplevel.activate) { // Running app - activate it - modelData.toplevel.activate() + modelData.toplevel.activate(); } else if (modelData?.appId) { // Pinned app not running - launch it - Quickshell.execDetached(["gtk-launch", modelData.appId]) + Quickshell.execDetached(["gtk-launch", modelData.appId]); } } } diff --git a/Modules/Dock/DockMenu.qml b/Modules/Dock/DockMenu.qml index ec2cb15f..9002a2a8 100644 --- a/Modules/Dock/DockMenu.qml +++ b/Modules/Dock/DockMenu.qml @@ -31,21 +31,21 @@ PopupWindow { function initItems() { // Is this a running app? - const isRunning = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel) + const isRunning = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel); // Is this a pinned app? - const isPinned = root.toplevel && root.isAppPinned(root.toplevel.appId) + const isPinned = root.toplevel && root.isAppPinned(root.toplevel.appId); - var next = [] + var next = []; if (isRunning) { // Focus item next.push({ "icon": "eye", "text": I18n.tr("dock.menu.focus"), "action": function () { - handleFocus() + handleFocus(); } - }) + }); } // Pin/Unpin item @@ -53,9 +53,9 @@ PopupWindow { "icon": !isPinned ? "pin" : "unpin", "text": !isPinned ? I18n.tr("dock.menu.pin") : I18n.tr("dock.menu.unpin"), "action": function () { - handlePin() + handlePin(); } - }) + }); if (isRunning) { // Close item @@ -63,55 +63,54 @@ PopupWindow { "icon": "close", "text": I18n.tr("dock.menu.close"), "action": function () { - handleClose() + handleClose(); } - }) + }); } // Create a menu entry for each app-specific action definied in its .desktop file if (typeof DesktopEntries !== 'undefined' && DesktopEntries.byId) { - const entry = (DesktopEntries.heuristicLookup) ? DesktopEntries.heuristicLookup(appId) : DesktopEntries.byId(appId) + const entry = (DesktopEntries.heuristicLookup) ? DesktopEntries.heuristicLookup(appId) : DesktopEntries.byId(appId); if (entry != null) { entry.actions.forEach(function (action) { next.push({ "icon": "", "text": action.name, "action": function () { - action.execute() + action.execute(); } - }) - }) + }); + }); } } - root.items = next + root.items = next; } // Helper functions for pin/unpin functionality function isAppPinned(appId) { if (!appId) - return false - const pinnedApps = Settings.data.dock.pinnedApps || [] - return pinnedApps.includes(appId) + return false; + const pinnedApps = Settings.data.dock.pinnedApps || []; + return pinnedApps.includes(appId); } function toggleAppPin(appId) { if (!appId) - return - - let pinnedApps = (Settings.data.dock.pinnedApps || []).slice() // Create a copy - const isPinned = pinnedApps.includes(appId) + return; + let pinnedApps = (Settings.data.dock.pinnedApps || []).slice(); // Create a copy + const isPinned = pinnedApps.includes(appId); if (isPinned) { // Unpin: remove from array - pinnedApps = pinnedApps.filter(id => id !== appId) + pinnedApps = pinnedApps.filter(id => id !== appId); } else { // Pin: add to array - pinnedApps.push(appId) + pinnedApps.push(appId); } // Update the settings - Settings.data.dock.pinnedApps = pinnedApps + Settings.data.dock.pinnedApps = pinnedApps; } anchor.item: anchorItem @@ -120,62 +119,62 @@ PopupWindow { function show(item, toplevelData) { if (!item) { - return + return; } - anchorItem = item - toplevel = toplevelData - initItems() - visible = true - canAutoClose = false - gracePeriodTimer.restart() + anchorItem = item; + toplevel = toplevelData; + initItems(); + visible = true; + canAutoClose = false; + gracePeriodTimer.restart(); } function hide() { - visible = false - root.items.length = 0 + visible = false; + root.items.length = 0; } // Helper function to determine which menu item is under the mouse function getHoveredItem(mouseY) { - const itemHeight = 32 - const startY = Style.marginM - const relativeY = mouseY - startY + const itemHeight = 32; + const startY = Style.marginM; + const relativeY = mouseY - startY; if (relativeY < 0) - return -1 + return -1; - const itemIndex = Math.floor(relativeY / itemHeight) - return itemIndex >= 0 && itemIndex < root.items.length ? itemIndex : -1 + const itemIndex = Math.floor(relativeY / itemHeight); + return itemIndex >= 0 && itemIndex < root.items.length ? itemIndex : -1; } function handleFocus() { if (root.toplevel?.activate) { - root.toplevel.activate() + root.toplevel.activate(); } - root.requestClose() + root.requestClose(); } function handlePin() { if (root.toplevel?.appId) { - root.toggleAppPin(root.toplevel.appId) + root.toggleAppPin(root.toplevel.appId); } - root.requestClose() + root.requestClose(); } function handleClose() { // Check if toplevel is still valid before trying to close it - const isValidToplevel = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel) + const isValidToplevel = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel); if (isValidToplevel && root.toplevel.close) { - root.toplevel.close() + root.toplevel.close(); // Trigger immediate dock update callback if provided if (root.onAppClosed && typeof root.onAppClosed === "function") { - Qt.callLater(root.onAppClosed) + Qt.callLater(root.onAppClosed); } } - root.hide() - root.requestClose() + root.hide(); + root.requestClose(); } // Short delay to ignore spurious events @@ -184,9 +183,9 @@ PopupWindow { interval: 1500 repeat: false onTriggered: { - root.canAutoClose = true + root.canAutoClose = true; if (!menuMouseArea.containsMouse) { - closeTimer.start() + closeTimer.start(); } } } @@ -197,7 +196,7 @@ PopupWindow { repeat: false running: false onTriggered: { - root.hide() + root.hide(); } } @@ -216,25 +215,25 @@ PopupWindow { cursorShape: root.hoveredItem >= 0 ? Qt.PointingHandCursor : Qt.ArrowCursor onEntered: { - closeTimer.stop() + closeTimer.stop(); } onExited: { - root.hoveredItem = -1 + root.hoveredItem = -1; if (root.canAutoClose) { // Only close if grace period has passed - closeTimer.start() + closeTimer.start(); } } onPositionChanged: mouse => { - root.hoveredItem = root.getHoveredItem(mouse.y) + root.hoveredItem = root.getHoveredItem(mouse.y); } onClicked: mouse => { - const clickedItem = root.getHoveredItem(mouse.y) + const clickedItem = root.getHoveredItem(mouse.y); if (clickedItem >= 0) { - root.items[clickedItem].action.call() + root.items[clickedItem].action.call(); } } } diff --git a/Modules/LockScreen/LockContext.qml b/Modules/LockScreen/LockContext.qml index e5c79bcf..c8c04b8f 100644 --- a/Modules/LockScreen/LockContext.qml +++ b/Modules/LockScreen/LockContext.qml @@ -18,24 +18,24 @@ Scope { onCurrentTextChanged: { if (currentText !== "") { - showFailure = false - errorMessage = "" + showFailure = false; + errorMessage = ""; } } function tryUnlock() { if (!pamAvailable) { - errorMessage = "PAM not available" - showFailure = true - return + errorMessage = "PAM not available"; + showFailure = true; + return; } - root.unlockInProgress = true - errorMessage = "" - showFailure = false + root.unlockInProgress = true; + errorMessage = ""; + showFailure = false; - Logger.i("LockContext", "Starting PAM authentication for user:", pam.user) - pam.start() + Logger.i("LockContext", "Starting PAM authentication for user:", pam.user); + pam.start(); } PamContext { @@ -44,48 +44,48 @@ Scope { user: HostService.username onPamMessage: { - Logger.i("LockContext", "PAM message:", message, "isError:", messageIsError, "responseRequired:", responseRequired) + Logger.i("LockContext", "PAM message:", message, "isError:", messageIsError, "responseRequired:", responseRequired); if (messageIsError) { - errorMessage = message + errorMessage = message; } else { - infoMessage = message + infoMessage = message; } if (responseRequired) { - Logger.i("LockContext", "Responding to PAM with password") - respond(root.currentText) + Logger.i("LockContext", "Responding to PAM with password"); + respond(root.currentText); } } onResponseRequiredChanged: { - Logger.i("LockContext", "Response required changed:", responseRequired) + Logger.i("LockContext", "Response required changed:", responseRequired); if (responseRequired && root.unlockInProgress) { - Logger.i("LockContext", "Automatically responding to PAM") - respond(root.currentText) + Logger.i("LockContext", "Automatically responding to PAM"); + respond(root.currentText); } } onCompleted: result => { - Logger.i("LockContext", "PAM completed with result:", result) + Logger.i("LockContext", "PAM completed with result:", result); if (result === PamResult.Success) { - Logger.i("LockContext", "Authentication successful") - root.unlocked() + Logger.i("LockContext", "Authentication successful"); + root.unlocked(); } else { - Logger.i("LockContext", "Authentication failed") - errorMessage = "Authentication failed" - showFailure = true - root.failed() + Logger.i("LockContext", "Authentication failed"); + errorMessage = "Authentication failed"; + showFailure = true; + root.failed(); } - root.unlockInProgress = false + root.unlockInProgress = false; } onError: { - Logger.i("LockContext", "PAM error:", error, "message:", message) - errorMessage = message || "Authentication error" - showFailure = true - root.unlockInProgress = false - root.failed() + Logger.i("LockContext", "PAM error:", error, "message:", message); + errorMessage = message || "Authentication error"; + showFailure = true; + root.unlockInProgress = false; + root.failed(); } } } diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index b4938c52..2a358fb0 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -1,21 +1,21 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls import QtQuick.Effects +import QtQuick.Layouts import Quickshell -import Quickshell.Wayland +import Quickshell.Io import Quickshell.Services.Pam import Quickshell.Services.UPower -import Quickshell.Io +import Quickshell.Wayland import Quickshell.Widgets import qs.Commons +import qs.Services.Compositor import qs.Services.Hardware import qs.Services.Keyboard import qs.Services.Location import qs.Services.Media -import qs.Services.Compositor -import qs.Services.UI import qs.Services.System +import qs.Services.UI import qs.Widgets import qs.Widgets.AudioSpectrum @@ -31,14 +31,14 @@ Loader { interval: 250 repeat: false onTriggered: { - lockScreen.active = false + lockScreen.active = false; // Reset the deprecation flag when unlocking - lockScreen.triggeredViaDeprecatedCall = false + lockScreen.triggeredViaDeprecatedCall = false; } } function scheduleUnloadAfterUnlock() { - unloadAfterUnlockTimer.start() + unloadAfterUnlockTimer.start(); } sourceComponent: Component { @@ -48,12 +48,12 @@ Loader { LockContext { id: lockContext onUnlocked: { - lockSession.locked = false - lockScreen.scheduleUnloadAfterUnlock() - lockContext.currentText = "" + lockSession.locked = false; + lockScreen.scheduleUnloadAfterUnlock(); + lockContext.currentText = ""; } onFailed: { - lockContext.currentText = "" + lockContext.currentText = ""; } } @@ -130,21 +130,20 @@ Loader { smooth: false onPaint: { - const ctx = getContext("2d") + const ctx = getContext("2d"); if (!ctx) - return + return; + ctx.reset(); + ctx.clearRect(0, 0, width, height); - ctx.reset() - ctx.clearRect(0, 0, width, height) + ctx.fillStyle = parent.cornerColor; + ctx.fillRect(0, 0, width, height); - ctx.fillStyle = parent.cornerColor - ctx.fillRect(0, 0, width, height) - - ctx.globalCompositeOperation = "destination-out" - ctx.fillStyle = "#ffffff" - ctx.beginPath() - ctx.arc(width, height, parent.cornerRadius, 0, 2 * Math.PI) - ctx.fill() + ctx.globalCompositeOperation = "destination-out"; + ctx.fillStyle = "#ffffff"; + ctx.beginPath(); + ctx.arc(width, height, parent.cornerRadius, 0, 2 * Math.PI); + ctx.fill(); } onWidthChanged: if (available) @@ -164,21 +163,20 @@ Loader { smooth: true onPaint: { - const ctx = getContext("2d") + const ctx = getContext("2d"); if (!ctx) - return + return; + ctx.reset(); + ctx.clearRect(0, 0, width, height); - ctx.reset() - ctx.clearRect(0, 0, width, height) + ctx.fillStyle = parent.cornerColor; + ctx.fillRect(0, 0, width, height); - ctx.fillStyle = parent.cornerColor - ctx.fillRect(0, 0, width, height) - - ctx.globalCompositeOperation = "destination-out" - ctx.fillStyle = "#ffffff" - ctx.beginPath() - ctx.arc(0, height, parent.cornerRadius, 0, 2 * Math.PI) - ctx.fill() + ctx.globalCompositeOperation = "destination-out"; + ctx.fillStyle = "#ffffff"; + ctx.beginPath(); + ctx.arc(0, height, parent.cornerRadius, 0, 2 * Math.PI); + ctx.fill(); } onWidthChanged: if (available) @@ -198,21 +196,20 @@ Loader { smooth: true onPaint: { - const ctx = getContext("2d") + const ctx = getContext("2d"); if (!ctx) - return + return; + ctx.reset(); + ctx.clearRect(0, 0, width, height); - ctx.reset() - ctx.clearRect(0, 0, width, height) + ctx.fillStyle = parent.cornerColor; + ctx.fillRect(0, 0, width, height); - ctx.fillStyle = parent.cornerColor - ctx.fillRect(0, 0, width, height) - - ctx.globalCompositeOperation = "destination-out" - ctx.fillStyle = "#ffffff" - ctx.beginPath() - ctx.arc(width, 0, parent.cornerRadius, 0, 2 * Math.PI) - ctx.fill() + ctx.globalCompositeOperation = "destination-out"; + ctx.fillStyle = "#ffffff"; + ctx.beginPath(); + ctx.arc(width, 0, parent.cornerRadius, 0, 2 * Math.PI); + ctx.fill(); } onWidthChanged: if (available) @@ -232,21 +229,20 @@ Loader { smooth: true onPaint: { - const ctx = getContext("2d") + const ctx = getContext("2d"); if (!ctx) - return + return; + ctx.reset(); + ctx.clearRect(0, 0, width, height); - ctx.reset() - ctx.clearRect(0, 0, width, height) + ctx.fillStyle = parent.cornerColor; + ctx.fillRect(0, 0, width, height); - ctx.fillStyle = parent.cornerColor - ctx.fillRect(0, 0, width, height) - - ctx.globalCompositeOperation = "destination-out" - ctx.fillStyle = "#ffffff" - ctx.beginPath() - ctx.arc(0, 0, parent.cornerRadius, 0, 2 * Math.PI) - ctx.fill() + ctx.globalCompositeOperation = "destination-out"; + ctx.fillStyle = "#ffffff"; + ctx.beginPath(); + ctx.arc(0, 0, parent.cornerRadius, 0, 2 * Math.PI); + ctx.fill(); } onWidthChanged: if (available) @@ -347,7 +343,7 @@ Loader { // Date below NText { text: { - var lang = I18n.locale.name.split("_")[0] + var lang = I18n.locale.name.split("_")[0]; var formats = { "de": "dddd, d. MMMM", "es": "dddd, d 'de' MMMM", @@ -356,8 +352,8 @@ Loader { "zh": "yyyy年M月d日 dddd", "uk": "dddd, d MMMM", "tr": "dddd, d MMMM" - } - return I18n.locale.toString(Time.now, formats[lang] || "dddd, MMMM d") + }; + return I18n.locale.toString(Time.now, formats[lang] || "dddd, MMMM d"); } pointSize: Style.fontSizeXL font.weight: Font.Medium @@ -487,15 +483,15 @@ Loader { // Compact status indicators container (compact mode only) Rectangle { width: { - var hasBattery = UPower.displayDevice && UPower.displayDevice.ready && UPower.displayDevice.isPresent - var hasKeyboard = keyboardLayout.currentLayout !== "Unknown" + var hasBattery = UPower.displayDevice && UPower.displayDevice.ready && UPower.displayDevice.isPresent; + var hasKeyboard = keyboardLayout.currentLayout !== "Unknown"; if (hasBattery && hasKeyboard) { - return 200 + return 200; } else if (hasBattery || hasKeyboard) { - return 120 + return 120; } else { - return 0 + return 0; } } height: 40 @@ -708,14 +704,14 @@ Loader { NText { text: { - var temp = LocationService.data.weather.current_weather.temperature - var suffix = "C" + var temp = LocationService.data.weather.current_weather.temperature; + var suffix = "C"; if (Settings.data.location.useFahrenheit) { - temp = LocationService.celsiusToFahrenheit(temp) - suffix = "F" + temp = LocationService.celsiusToFahrenheit(temp); + suffix = "F"; } - temp = Math.round(temp) - return temp + "°" + suffix + temp = Math.round(temp); + return temp + "°" + suffix; } pointSize: Style.fontSizeXL font.weight: Style.fontWeightBold @@ -724,14 +720,14 @@ Loader { NText { text: { - var wind = LocationService.data.weather.current_weather.windspeed - var unit = "km/h" + var wind = LocationService.data.weather.current_weather.windspeed; + var unit = "km/h"; if (Settings.data.location.useFahrenheit) { - wind = wind * 0.621371 // Convert km/h to mph - unit = "mph" + wind = wind * 0.621371; // Convert km/h to mph + unit = "mph"; } - wind = Math.round(wind) - return wind + " " + unit + wind = Math.round(wind); + return wind + " " + unit; } pointSize: Style.fontSizeM color: Color.mOnSurfaceVariant @@ -773,8 +769,8 @@ Loader { NText { text: { - var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/")) - return I18n.locale.toString(weatherDate, "ddd") + var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/")); + return I18n.locale.toString(weatherDate, "ddd"); } pointSize: Style.fontSizeM color: Color.mOnSurfaceVariant @@ -791,15 +787,15 @@ Loader { NText { text: { - var max = LocationService.data.weather.daily.temperature_2m_max[index] - var min = LocationService.data.weather.daily.temperature_2m_min[index] + var max = LocationService.data.weather.daily.temperature_2m_max[index]; + var min = LocationService.data.weather.daily.temperature_2m_min[index]; if (Settings.data.location.useFahrenheit) { - max = LocationService.celsiusToFahrenheit(max) - min = LocationService.celsiusToFahrenheit(min) + max = LocationService.celsiusToFahrenheit(max); + min = LocationService.celsiusToFahrenheit(min); } - max = Math.round(max) - min = Math.round(min) - return max + "°/" + min + "°" + max = Math.round(max); + min = Math.round(min); + return max + "°/" + min + "°"; } pointSize: Style.fontSizeM font.weight: Style.fontWeightMedium @@ -916,7 +912,7 @@ Loader { Keys.onPressed: function (event) { if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { - lockContext.tryUnlock() + lockContext.tryUnlock(); } } diff --git a/Modules/MainScreen/AllScreens.qml b/Modules/MainScreen/AllScreens.qml index bf586ef7..79789b44 100644 --- a/Modules/MainScreen/AllScreens.qml +++ b/Modules/MainScreen/AllScreens.qml @@ -3,8 +3,8 @@ import Quickshell import Quickshell.Wayland import qs.Commons -import qs.Services.UI import qs.Modules.MainScreen +import qs.Services.UI // ------------------------------ // MainScreen for each screen (manages bar + all panels) @@ -16,10 +16,10 @@ Variants { property bool shouldBeActive: { if (!modelData || !modelData.name) { - return false + return false; } - Logger.d("Shell", "MainScreen activated for", modelData?.name) - return true + Logger.d("Shell", "MainScreen activated for", modelData?.name); + return true; } property bool windowLoaded: false @@ -33,7 +33,7 @@ Variants { onLoaded: { // Signal that window is loaded so exclusion zone can be created - parent.windowLoaded = true + parent.windowLoaded = true; } sourceComponent: MainScreen { @@ -45,11 +45,11 @@ Variants { Loader { active: { if (!parent.windowLoaded || !parent.shouldBeActive || !BarService.isVisible) - return false + return false; // Check if bar is configured for this screen - var monitors = Settings.data.bar.monitors || [] - return monitors.length === 0 || monitors.includes(modelData?.name) + var monitors = Settings.data.bar.monitors || []; + return monitors.length === 0 || monitors.includes(modelData?.name); } asynchronous: false @@ -58,7 +58,7 @@ Variants { } onLoaded: { - Logger.d("Shell", "BarContentWindow created for", modelData?.name) + Logger.d("Shell", "BarContentWindow created for", modelData?.name); } } @@ -67,11 +67,11 @@ Variants { Loader { active: { if (!parent.windowLoaded || !parent.shouldBeActive || !BarService.isVisible) - return false + return false; // Check if bar is configured for this screen - var monitors = Settings.data.bar.monitors || [] - return monitors.length === 0 || monitors.includes(modelData?.name) + var monitors = Settings.data.bar.monitors || []; + return monitors.length === 0 || monitors.includes(modelData?.name); } asynchronous: false @@ -80,7 +80,7 @@ Variants { } onLoaded: { - Logger.d("Shell", "BarExclusionZone created for", modelData?.name) + Logger.d("Shell", "BarExclusionZone created for", modelData?.name); } } @@ -95,7 +95,7 @@ Variants { } onLoaded: { - Logger.d("Shell", "TrayMenuWindow created for", modelData?.name) + Logger.d("Shell", "TrayMenuWindow created for", modelData?.name); } } } diff --git a/Modules/MainScreen/Backgrounds/AllBackgrounds.qml b/Modules/MainScreen/Backgrounds/AllBackgrounds.qml index 50123f9a..7e1bc5c6 100644 --- a/Modules/MainScreen/Backgrounds/AllBackgrounds.qml +++ b/Modules/MainScreen/Backgrounds/AllBackgrounds.qml @@ -3,17 +3,16 @@ import QtQuick.Shapes import qs.Commons import qs.Widgets - /** - * AllBackgrounds - Unified Shape container for all bar and panel backgrounds - * - * Unified shadow system. This component contains a single Shape - * with multiple ShapePath children (one for bar, one for each panel type). - * - * Benefits: - * - Single GPU-accelerated rendering pass for all backgrounds - * - Unified shadow system (one MultiEffect for everything) - */ +* AllBackgrounds - Unified Shape container for all bar and panel backgrounds +* +* Unified shadow system. This component contains a single Shape +* with multiple ShapePath children (one for bar, one for each panel type). +* +* Benefits: +* - Single GPU-accelerated rendering pass for all backgrounds +* - Unified shadow system (one MultiEffect for everything) +*/ Item { id: root @@ -46,15 +45,14 @@ Item { enabled: false // Disable mouse input on the Shape itself Component.onCompleted: { - Logger.d("AllBackgrounds", "AllBackgrounds initialized") - Logger.d("AllBackgrounds", " bar:", root.bar) - Logger.d("AllBackgrounds", " windowRoot:", root.windowRoot) + Logger.d("AllBackgrounds", "AllBackgrounds initialized"); + Logger.d("AllBackgrounds", " bar:", root.bar); + Logger.d("AllBackgrounds", " windowRoot:", root.windowRoot); } - /** - * Bar - */ + * Bar + */ BarBackground { bar: root.bar shapeContainer: backgroundsShape @@ -62,10 +60,9 @@ Item { backgroundColor: Qt.alpha(Color.mSurface, Settings.data.bar.backgroundOpacity) } - /** - * Panels - */ + * Panels + */ // Audio PanelBackground { @@ -74,13 +71,6 @@ Item { backgroundColor: panelBackgroundColor } - // Battery - PanelBackground { - panel: root.windowRoot.batteryPanelPlaceholder - shapeContainer: backgroundsShape - backgroundColor: panelBackgroundColor - } - // Bluetooth PanelBackground { panel: root.windowRoot.bluetoothPanelPlaceholder diff --git a/Modules/MainScreen/Backgrounds/BarBackground.qml b/Modules/MainScreen/Backgrounds/BarBackground.qml index 11fd0404..cb8e0456 100644 --- a/Modules/MainScreen/Backgrounds/BarBackground.qml +++ b/Modules/MainScreen/Backgrounds/BarBackground.qml @@ -1,22 +1,21 @@ import QtQuick import QtQuick.Shapes import qs.Commons -import qs.Services.UI import qs.Modules.MainScreen.Backgrounds - +import qs.Services.UI /** - * BarBackground - ShapePath component for rendering the bar background - * - * Unified shadow system. This component is a ShapePath that will be - * a child of the unified AllBackgrounds Shape container. - * - * Uses 4-state per-corner system for flexible corner rendering: - * - State -1: No radius (flat/square corner) - * - State 0: Normal (inner curve) - * - State 1: Horizontal inversion (outer curve on X-axis) - * - State 2: Vertical inversion (outer curve on Y-axis) - */ +* BarBackground - ShapePath component for rendering the bar background +* +* Unified shadow system. This component is a ShapePath that will be +* a child of the unified AllBackgrounds Shape container. +* +* Uses 4-state per-corner system for flexible corner rendering: +* - State -1: No radius (flat/square corner) +* - State 0: Normal (inner curve) +* - State 1: Horizontal inversion (outer curve on X-axis) +* - State 2: Vertical inversion (outer curve on Y-axis) +*/ ShapePath { id: root @@ -35,15 +34,15 @@ ShapePath { readonly property bool shouldShow: { // Check global bar visibility if (!BarService.isVisible) - return false + return false; // Check screen-specific configuration - var monitors = Settings.data.bar.monitors || [] - var screenName = windowRoot?.screen?.name || "" + var monitors = Settings.data.bar.monitors || []; + var screenName = windowRoot?.screen?.name || ""; // If no monitors specified, show on all screens // If monitors specified, only show if this screen is in the list - return monitors.length === 0 || monitors.includes(screenName) + return monitors.length === 0 || monitors.includes(screenName); } // Corner radius (from Style) @@ -65,9 +64,9 @@ ShapePath { function getCornerRadius(cornerState) { // State -1 = no radius (flat corner) if (cornerState === -1) - return 0 + return 0; // All other states use effectiveRadius - return effectiveRadius + return effectiveRadius; } // Per-corner multipliers and radii based on bar's corner states (handle null bar) diff --git a/Modules/MainScreen/Backgrounds/PanelBackground.qml b/Modules/MainScreen/Backgrounds/PanelBackground.qml index 82ce35ad..528db3d3 100644 --- a/Modules/MainScreen/Backgrounds/PanelBackground.qml +++ b/Modules/MainScreen/Backgrounds/PanelBackground.qml @@ -3,22 +3,21 @@ import QtQuick.Shapes import qs.Commons import qs.Modules.MainScreen.Backgrounds - /** - * PanelBackground - ShapePath component for rendering a single background - * - * Unified shadow system. This component is a ShapePath that will - * be a child of the unified AllBackgrounds Shape container. - * - * Reads positioning and geometry from PanelPlaceholder (via panel.panelItem). - * The actual panel content lives in a separate SmartPanelWindow. - * - * Uses 4-state per-corner system for flexible corner rendering: - * - State -1: No radius (flat/square corner) - * - State 0: Normal (inner curve) - * - State 1: Horizontal inversion (outer curve on X-axis) - * - State 2: Vertical inversion (outer curve on Y-axis) - */ +* PanelBackground - ShapePath component for rendering a single background +* +* Unified shadow system. This component is a ShapePath that will +* be a child of the unified AllBackgrounds Shape container. +* +* Reads positioning and geometry from PanelPlaceholder (via panel.panelItem). +* The actual panel content lives in a separate SmartPanelWindow. +* +* Uses 4-state per-corner system for flexible corner rendering: +* - State -1: No radius (flat/square corner) +* - State 0: Normal (inner curve) +* - State 1: Horizontal inversion (outer curve on X-axis) +* - State 2: Vertical inversion (outer curve on Y-axis) +*/ ShapePath { id: root @@ -51,9 +50,9 @@ ShapePath { function getCornerRadius(cornerState) { // State -1 = no radius (flat corner) if (cornerState === -1) - return 0 + return 0; // All other states use effectiveRadius - return effectiveRadius + return effectiveRadius; } // Per-corner multipliers and radii based on panelBg's corner states diff --git a/Modules/MainScreen/Backgrounds/ShapeCornerHelper.qml b/Modules/MainScreen/Backgrounds/ShapeCornerHelper.qml index 3e766c7a..f53cc672 100644 --- a/Modules/MainScreen/Backgrounds/ShapeCornerHelper.qml +++ b/Modules/MainScreen/Backgrounds/ShapeCornerHelper.qml @@ -4,78 +4,71 @@ import QtQuick import QtQuick.Shapes import Quickshell - /** - * ShapeCornerHelper - Utility singleton for shape corner calculations - * - * Uses 4-state per-corner system for flexible corner rendering: - * - State -1: No radius (flat/square corner) - * - State 0: Normal (inner curve) - * - State 1: Horizontal inversion (outer curve on X-axis) - * - State 2: Vertical inversion (outer curve on Y-axis) - * - * The key technique: Using PathArc direction control (Clockwise vs Counterclockwise) - * combined with multipliers to create both inner and outer corner curves. - */ +* ShapeCornerHelper - Utility singleton for shape corner calculations +* +* Uses 4-state per-corner system for flexible corner rendering: +* - State -1: No radius (flat/square corner) +* - State 0: Normal (inner curve) +* - State 1: Horizontal inversion (outer curve on X-axis) +* - State 2: Vertical inversion (outer curve on Y-axis) +* +* The key technique: Using PathArc direction control (Clockwise vs Counterclockwise) +* combined with multipliers to create both inner and outer corner curves. +*/ Singleton { id: root - /** - * Get X-axis multiplier for a corner state - * State 1 (horizontal invert) returns -1, others return 1 - */ + * Get X-axis multiplier for a corner state + * State 1 (horizontal invert) returns -1, others return 1 + */ function getMultX(cornerState) { - return cornerState === 1 ? -1 : 1 + return cornerState === 1 ? -1 : 1; } - /** - * Get Y-axis multiplier for a corner state - * State 2 (vertical invert) returns -1, others return 1 - */ + * Get Y-axis multiplier for a corner state + * State 2 (vertical invert) returns -1, others return 1 + */ function getMultY(cornerState) { - return cornerState === 2 ? -1 : 1 + return cornerState === 2 ? -1 : 1; } - /** - * Get PathArc direction for a corner based on its multipliers - * Uses XOR logic: if X inverted differs from Y inverted, use Counterclockwise - * This creates the outer curve effect for inverted corners - */ + * Get PathArc direction for a corner based on its multipliers + * Uses XOR logic: if X inverted differs from Y inverted, use Counterclockwise + * This creates the outer curve effect for inverted corners + */ function getArcDirection(multX, multY) { - return ((multX < 0) !== (multY < 0)) ? PathArc.Counterclockwise : PathArc.Clockwise + return ((multX < 0) !== (multY < 0)) ? PathArc.Counterclockwise : PathArc.Clockwise; } - /** - * Convenience function to get arc direction directly from corner state - */ + * Convenience function to get arc direction directly from corner state + */ function getArcDirectionFromState(cornerState) { - const multX = getMultX(cornerState) - const multY = getMultY(cornerState) - return getArcDirection(multX, multY) + const multX = getMultX(cornerState); + const multY = getMultY(cornerState); + return getArcDirection(multX, multY); } - /** - * Get the "flattening" radius when shape dimensions are too small - * Prevents visual artifacts when radius exceeds dimensions - */ + * Get the "flattening" radius when shape dimensions are too small + * Prevents visual artifacts when radius exceeds dimensions + */ function getFlattenedRadius(dimension, requestedRadius) { if (dimension < requestedRadius * 2) { - return dimension / 2 + return dimension / 2; } - return requestedRadius + return requestedRadius; } - /** - * Check if a shape should use flattened corners - * Returns true if width or height is too small for the requested radius - */ + * Check if a shape should use flattened corners + * Returns true if width or height is too small for the requested radius + */ function shouldFlatten(width, height, radius) { - return width < radius * 2 || height < radius * 2 + return width < radius * 2 || height < radius * 2; } } diff --git a/Modules/MainScreen/BarContentWindow.qml b/Modules/MainScreen/BarContentWindow.qml index d332447d..51471aad 100644 --- a/Modules/MainScreen/BarContentWindow.qml +++ b/Modules/MainScreen/BarContentWindow.qml @@ -2,19 +2,18 @@ import QtQuick import Quickshell import Quickshell.Wayland import qs.Commons -import qs.Services.UI import qs.Modules.Bar - +import qs.Services.UI /** - * BarContentWindow - Separate transparent PanelWindow for bar content - * - * This window contains only the bar widgets (content), while the background - * is rendered in MainScreen's unified Shape system. This separation prevents - * fullscreen redraws when bar widgets redraw. - * - * This component should be instantiated once per screen by AllScreens.qml - */ +* BarContentWindow - Separate transparent PanelWindow for bar content +* +* This window contains only the bar widgets (content), while the background +* is rendered in MainScreen's unified Shape system. This separation prevents +* fullscreen redraws when bar widgets redraw. +* +* This component should be instantiated once per screen by AllScreens.qml +*/ PanelWindow { id: barWindow @@ -22,7 +21,7 @@ PanelWindow { color: Color.transparent // Transparent - background is in MainScreen below Component.onCompleted: { - Logger.d("BarContentWindow", "Bar content window created for screen:", barWindow.screen?.name) + Logger.d("BarContentWindow", "Bar content window created for screen:", barWindow.screen?.name); } // Wayland layer configuration diff --git a/Modules/MainScreen/BarExclusionZone.qml b/Modules/MainScreen/BarExclusionZone.qml index d8072355..ea0506b1 100644 --- a/Modules/MainScreen/BarExclusionZone.qml +++ b/Modules/MainScreen/BarExclusionZone.qml @@ -3,13 +3,12 @@ import Quickshell import Quickshell.Wayland import qs.Commons - /** - * BarExclusionZone - Invisible PanelWindow that reserves exclusive space for the bar - * - * This is a minimal window that works with the compositor to reserve space, - * while the actual bar UI is rendered in MainScreen. - */ +* BarExclusionZone - Invisible PanelWindow that reserves exclusive space for the bar +* +* This is a minimal window that works with the compositor to reserve space, +* while the actual bar UI is rendered in MainScreen. +*/ PanelWindow { id: root @@ -46,11 +45,11 @@ PanelWindow { // Vertical bar: reserve bar height + margin on the anchored edge only if (barFloating) { // For left bar, reserve left margin; for right bar, reserve right margin - return Style.barHeight + barMarginH + return Style.barHeight + barMarginH; } - return Style.barHeight + return Style.barHeight; } - return 0 // Auto-width when left/right anchors are true + return 0; // Auto-width when left/right anchors are true } implicitHeight: { @@ -58,17 +57,17 @@ PanelWindow { // Horizontal bar: reserve bar height + margin on the anchored edge only if (barFloating) { // For top bar, reserve top margin; for bottom bar, reserve bottom margin - return Style.barHeight + barMarginV + return Style.barHeight + barMarginV; } - return Style.barHeight + return Style.barHeight; } - return 0 // Auto-height when top/bottom anchors are true + return 0; // Auto-height when top/bottom anchors are true } Component.onCompleted: { - Logger.d("BarExclusionZone", "Created for screen:", screen?.name) - Logger.d("BarExclusionZone", " Position:", barPosition, "Exclusive:", exclusive, "Floating:", barFloating) - Logger.d("BarExclusionZone", " Anchors - top:", anchors.top, "bottom:", anchors.bottom, "left:", anchors.left, "right:", anchors.right) - Logger.d("BarExclusionZone", " Size:", width, "x", height, "implicitWidth:", implicitWidth, "implicitHeight:", implicitHeight) + Logger.d("BarExclusionZone", "Created for screen:", screen?.name); + Logger.d("BarExclusionZone", " Position:", barPosition, "Exclusive:", exclusive, "Floating:", barFloating); + Logger.d("BarExclusionZone", " Anchors - top:", anchors.top, "bottom:", anchors.bottom, "left:", anchors.left, "right:", anchors.right); + Logger.d("BarExclusionZone", " Size:", width, "x", height, "implicitWidth:", implicitWidth, "implicitHeight:", implicitHeight); } } diff --git a/Modules/MainScreen/MainScreen.qml b/Modules/MainScreen/MainScreen.qml index e72bed29..f851aa86 100644 --- a/Modules/MainScreen/MainScreen.qml +++ b/Modules/MainScreen/MainScreen.qml @@ -2,16 +2,14 @@ import QtQuick import QtQuick.Effects import Quickshell import Quickshell.Wayland +import "Backgrounds" as Backgrounds import qs.Commons -import qs.Services.UI -import "Backgrounds" as Backgrounds // All panels import qs.Modules.Bar import qs.Modules.Bar.Extras import qs.Modules.Panels.Audio -import qs.Modules.Panels.Battery import qs.Modules.Panels.Bluetooth import qs.Modules.Panels.Calendar import qs.Modules.Panels.ControlCenter @@ -23,17 +21,16 @@ import qs.Modules.Panels.SetupWizard import qs.Modules.Panels.Tray import qs.Modules.Panels.Wallpaper import qs.Modules.Panels.WiFi - +import qs.Services.UI /** - * MainScreen - Single PanelWindow per screen that manages all panels and the bar - */ +* MainScreen - Single PanelWindow per screen that manages all panels and the bar +*/ PanelWindow { id: root // Expose panels as readonly property aliases readonly property alias audioPanel: audioPanel - readonly property alias batteryPanel: batteryPanel readonly property alias bluetoothPanel: bluetoothPanel readonly property alias calendarPanel: calendarPanel readonly property alias controlCenterPanel: controlCenterPanel @@ -48,7 +45,6 @@ PanelWindow { // Expose panel placeholders for AllBackgrounds readonly property var audioPanelPlaceholder: audioPanel.panelPlaceholder - readonly property var batteryPanelPlaceholder: batteryPanel.panelPlaceholder readonly property var bluetoothPanelPlaceholder: bluetoothPanel.panelPlaceholder readonly property var calendarPanelPlaceholder: calendarPanel.panelPlaceholder readonly property var controlCenterPanelPlaceholder: controlCenterPanel.panelPlaceholder @@ -62,7 +58,7 @@ PanelWindow { readonly property var wifiPanelPlaceholder: wifiPanel.panelPlaceholder Component.onCompleted: { - Logger.d("MainScreen", "Initialized for screen:", screen?.name, "- Dimensions:", screen?.width, "x", screen?.height, "- Position:", screen?.x, ",", screen?.y) + Logger.d("MainScreen", "Initialized for screen:", screen?.name, "- Dimensions:", screen?.width, "x", screen?.height, "- Position:", screen?.x, ",", screen?.y); } // Wayland @@ -85,9 +81,9 @@ PanelWindow { color: { if (dimmerOpacity > 0 && isPanelOpen && !isPanelClosing) { - return Qt.alpha(Color.mShadow, dimmerOpacity) + return Qt.alpha(Color.mShadow, dimmerOpacity); } - return Color.transparent + return Color.transparent; } Behavior on color { @@ -101,15 +97,15 @@ PanelWindow { readonly property bool barShouldShow: { // Check global bar visibility if (!BarService.isVisible) - return false + return false; // Check screen-specific configuration - var monitors = Settings.data.bar.monitors || [] - var screenName = screen?.name || "" + var monitors = Settings.data.bar.monitors || []; + var screenName = screen?.name || ""; // If no monitors specified, show on all screens // If monitors specified, only show if this screen is in the list - return monitors.length === 0 || monitors.includes(screenName) + return monitors.length === 0 || monitors.includes(screenName); } // Make everything click-through except bar @@ -166,19 +162,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "audioPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(audioPanel) - } - } - - BatteryPanel { - id: batteryPanel - screen: root.screen - z: 50 - - Component.onCompleted: { - objectName = "batteryPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(batteryPanel) + objectName = "audioPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(audioPanel); } } @@ -188,8 +173,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "bluetoothPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(bluetoothPanel) + objectName = "bluetoothPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(bluetoothPanel); } } @@ -199,8 +184,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "controlCenterPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(controlCenterPanel) + objectName = "controlCenterPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(controlCenterPanel); } } @@ -210,8 +195,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "calendarPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(calendarPanel) + objectName = "calendarPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(calendarPanel); } } @@ -221,8 +206,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "launcherPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(launcherPanel) + objectName = "launcherPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(launcherPanel); } } @@ -232,8 +217,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "notificationHistoryPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(notificationHistoryPanel) + objectName = "notificationHistoryPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(notificationHistoryPanel); } } @@ -243,8 +228,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "sessionMenuPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(sessionMenuPanel) + objectName = "sessionMenuPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(sessionMenuPanel); } } @@ -254,8 +239,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "settingsPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(settingsPanel) + objectName = "settingsPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(settingsPanel); } } @@ -265,8 +250,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "setupWizardPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(setupWizardPanel) + objectName = "setupWizardPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(setupWizardPanel); } } @@ -276,8 +261,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "trayDrawerPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(trayDrawerPanel) + objectName = "trayDrawerPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(trayDrawerPanel); } } @@ -287,8 +272,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "wallpaperPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(wallpaperPanel) + objectName = "wallpaperPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(wallpaperPanel); } } @@ -298,8 +283,8 @@ PanelWindow { z: 50 Component.onCompleted: { - objectName = "wifiPanel-" + (screen?.name || "unknown") - PanelService.registerPanel(wifiPanel) + objectName = "wifiPanel-" + (screen?.name || "unknown"); + PanelService.registerPanel(wifiPanel); } } @@ -326,94 +311,93 @@ PanelWindow { // Use screen dimensions directly x: { if (barPosition === "right") - return screen.width - Style.barHeight - barMarginH - attachmentOverlap // Extend left towards panels - return barMarginH + return screen.width - Style.barHeight - barMarginH - attachmentOverlap; // Extend left towards panels + return barMarginH; } y: { if (barPosition === "bottom") - return screen.height - Style.barHeight - barMarginV - attachmentOverlap - return barMarginV + return screen.height - Style.barHeight - barMarginV - attachmentOverlap; + return barMarginV; } width: { if (barIsVertical) { - return Style.barHeight + attachmentOverlap + return Style.barHeight + attachmentOverlap; } - return screen.width - barMarginH * 2 + return screen.width - barMarginH * 2; } height: { if (barIsVertical) { - return screen.height - barMarginV * 2 + return screen.height - barMarginV * 2; } - return Style.barHeight + attachmentOverlap + return Style.barHeight + attachmentOverlap; } // Corner states (same as Bar.qml) readonly property int topLeftCornerState: { if (barFloating) - return 0 + return 0; if (barPosition === "top") - return -1 + return -1; if (barPosition === "left") - return -1 + return -1; if (Settings.data.bar.outerCorners && (barPosition === "bottom" || barPosition === "right")) { - return barIsVertical ? 1 : 2 + return barIsVertical ? 1 : 2; } - return -1 + return -1; } readonly property int topRightCornerState: { if (barFloating) - return 0 + return 0; if (barPosition === "top") - return -1 + return -1; if (barPosition === "right") - return -1 + return -1; if (Settings.data.bar.outerCorners && (barPosition === "bottom" || barPosition === "left")) { - return barIsVertical ? 1 : 2 + return barIsVertical ? 1 : 2; } - return -1 + return -1; } readonly property int bottomLeftCornerState: { if (barFloating) - return 0 + return 0; if (barPosition === "bottom") - return -1 + return -1; if (barPosition === "left") - return -1 + return -1; if (Settings.data.bar.outerCorners && (barPosition === "top" || barPosition === "right")) { - return barIsVertical ? 1 : 2 + return barIsVertical ? 1 : 2; } - return -1 + return -1; } readonly property int bottomRightCornerState: { if (barFloating) - return 0 + return 0; if (barPosition === "bottom") - return -1 + return -1; if (barPosition === "right") - return -1 + return -1; if (Settings.data.bar.outerCorners && (barPosition === "top" || barPosition === "left")) { - return barIsVertical ? 1 : 2 + return barIsVertical ? 1 : 2; } - return -1 + return -1; } Component.onCompleted: { - Logger.d("MainScreen", "===== Bar placeholder loaded =====") - Logger.d("MainScreen", " Screen:", screen?.name, "Size:", screen?.width, "x", screen?.height) - Logger.d("MainScreen", " Bar position:", barPosition, "| isVertical:", barIsVertical) - Logger.d("MainScreen", " Bar dimensions: x=" + x, "y=" + y, "width=" + width, "height=" + height) - Logger.d("MainScreen", " Style.barHeight =", Style.barHeight) - Logger.d("MainScreen", " Margins: H=" + barMarginH, "V=" + barMarginV, "| Floating:", barFloating) + Logger.d("MainScreen", "===== Bar placeholder loaded ====="); + Logger.d("MainScreen", " Screen:", screen?.name, "Size:", screen?.width, "x", screen?.height); + Logger.d("MainScreen", " Bar position:", barPosition, "| isVertical:", barIsVertical); + Logger.d("MainScreen", " Bar dimensions: x=" + x, "y=" + y, "width=" + width, "height=" + height); + Logger.d("MainScreen", " Style.barHeight =", Style.barHeight); + Logger.d("MainScreen", " Margins: H=" + barMarginH, "V=" + barMarginV, "| Floating:", barFloating); } } - /** - * Screen Corners - */ + * Screen Corners + */ ScreenCorners {} } } diff --git a/Modules/MainScreen/PanelPlaceholder.qml b/Modules/MainScreen/PanelPlaceholder.qml index af50d4c4..9782a004 100644 --- a/Modules/MainScreen/PanelPlaceholder.qml +++ b/Modules/MainScreen/PanelPlaceholder.qml @@ -3,14 +3,13 @@ import Quickshell import qs.Commons import qs.Services.UI - /** - * PanelPlaceholder - Lightweight positioning logic for panel backgrounds - * - * This component stays in MainScreen and provides geometry for PanelBackground rendering. - * It contains only positioning calculations and animations, no visual content. - * The actual panel content lives in a separate SmartPanelWindow. - */ +* PanelPlaceholder - Lightweight positioning logic for panel backgrounds +* +* This component stays in MainScreen and provides geometry for PanelBackground rendering. +* It contains only positioning calculations and animations, no visual content. +* The actual panel content lives in a separate SmartPanelWindow. +*/ Item { id: root @@ -71,13 +70,13 @@ Item { readonly property bool allowAttach: Settings.data.ui.panelsAttachedToBar || root.forceAttachToBar readonly property bool allowAttachToBar: { if (!(Settings.data.ui.panelsAttachedToBar || root.forceAttachToBar) || Settings.data.bar.backgroundOpacity < 1.0) { - return false + return false; } // A panel can only be attached to a bar if there is a bar on that screen - var monitors = Settings.data.bar.monitors || [] - var result = monitors.length === 0 || monitors.includes(root.screen?.name || "") - return result + var monitors = Settings.data.bar.monitors || []; + var result = monitors.length === 0 || monitors.includes(root.screen?.name || ""); + return result; } // Effective anchor properties (depend on allowAttach) @@ -97,17 +96,17 @@ Item { function onUiScaleRatioChanged() { if (root.isPanelVisible) { - root.setPosition() + root.setPosition(); } } } // Public function to update content size from SmartPanelWindow function updateContentSize(w, h) { - contentPreferredWidth = w - contentPreferredHeight = h + contentPreferredWidth = w; + contentPreferredHeight = h; if (isPanelVisible) { - setPosition() + setPosition(); } } @@ -115,45 +114,45 @@ Item { function setPosition() { // Don't calculate position if parent dimensions aren't available yet if (!root.width || !root.height) { - Logger.d("PanelPlaceholder", "Skipping setPosition - dimensions not ready:", root.width, "x", root.height, panelName) - Qt.callLater(setPosition) - return + Logger.d("PanelPlaceholder", "Skipping setPosition - dimensions not ready:", root.width, "x", root.height, panelName); + Qt.callLater(setPosition); + return; } // Calculate panel dimensions first (needed for positioning) - var w + var w; // Priority 1: Content-driven size (dynamic) if (contentPreferredWidth > 0) { - w = contentPreferredWidth + w = contentPreferredWidth; } // Priority 2: Ratio-based size else if (root.preferredWidthRatio !== undefined) { - w = Math.round(Math.max(root.width * root.preferredWidthRatio, root.preferredWidth)) + w = Math.round(Math.max(root.width * root.preferredWidthRatio, root.preferredWidth)); } // Priority 3: Static preferred width else { - w = root.preferredWidth + w = root.preferredWidth; } - var panelWidth = Math.min(w, root.width - Style.marginL * 2) + var panelWidth = Math.min(w, root.width - Style.marginL * 2); - var h + var h; // Priority 1: Content-driven size (dynamic) if (contentPreferredHeight > 0) { - h = contentPreferredHeight + h = contentPreferredHeight; } // Priority 2: Ratio-based size else if (root.preferredHeightRatio !== undefined) { - h = Math.round(Math.max(root.height * root.preferredHeightRatio, root.preferredHeight)) + h = Math.round(Math.max(root.height * root.preferredHeightRatio, root.preferredHeight)); } // Priority 3: Static preferred height else { - h = root.preferredHeight + h = root.preferredHeight; } - var panelHeight = Math.min(h, root.height - Style.barHeight - Style.marginL * 2) + var panelHeight = Math.min(h, root.height - Style.barHeight - Style.marginL * 2); // Update panelBackground target size (will be animated) - panelBackground.targetWidth = panelWidth - panelBackground.targetHeight = panelHeight + panelBackground.targetWidth = panelWidth; + panelBackground.targetHeight = panelHeight; // Calculate position - var calculatedX - var calculatedY + var calculatedX; + var calculatedY; // ===== X POSITIONING ===== if (root.useButtonPosition && root.width > 0 && panelWidth > 0) { @@ -162,111 +161,111 @@ Item { if (allowAttach) { // Attached panels: align with bar edge (left or right side) if (root.barPosition === "left") { - var leftBarEdge = root.barMarginH + Style.barHeight - calculatedX = leftBarEdge + var leftBarEdge = root.barMarginH + Style.barHeight; + calculatedX = leftBarEdge; } else { // right - var rightBarEdge = root.width - root.barMarginH - Style.barHeight - calculatedX = rightBarEdge - panelWidth + var rightBarEdge = root.width - root.barMarginH - Style.barHeight; + calculatedX = rightBarEdge - panelWidth; } } else { // Detached panels: center on button X position - var panelX = root.buttonPosition.x + root.buttonWidth / 2 - panelWidth / 2 - var minX = Style.marginL - var maxX = root.width - panelWidth - Style.marginL + var panelX = root.buttonPosition.x + root.buttonWidth / 2 - panelWidth / 2; + var minX = Style.marginL; + var maxX = root.width - panelWidth - Style.marginL; // Account for vertical bar taking up space if (root.barPosition === "left") { - minX = root.barMarginH + Style.barHeight + Style.marginL + minX = root.barMarginH + Style.barHeight + Style.marginL; } else if (root.barPosition === "right") { - maxX = root.width - root.barMarginH - Style.barHeight - panelWidth - Style.marginL + maxX = root.width - root.barMarginH - Style.barHeight - panelWidth - Style.marginL; } - panelX = Math.max(minX, Math.min(panelX, maxX)) - calculatedX = panelX + panelX = Math.max(minX, Math.min(panelX, maxX)); + calculatedX = panelX; } } else { // For horizontal bars, center panel on button X position - var panelX = root.buttonPosition.x + root.buttonWidth / 2 - panelWidth / 2 + var panelX = root.buttonPosition.x + root.buttonWidth / 2 - panelWidth / 2; if (allowAttach) { - var cornerInset = root.barFloating ? Style.radiusL * 2 : 0 - var barLeftEdge = root.barMarginH + cornerInset - var barRightEdge = root.width - root.barMarginH - cornerInset - panelX = Math.max(barLeftEdge, Math.min(panelX, barRightEdge - panelWidth)) + var cornerInset = root.barFloating ? Style.radiusL * 2 : 0; + var barLeftEdge = root.barMarginH + cornerInset; + var barRightEdge = root.width - root.barMarginH - cornerInset; + panelX = Math.max(barLeftEdge, Math.min(panelX, barRightEdge - panelWidth)); } else { - panelX = Math.max(Style.marginL, Math.min(panelX, root.width - panelWidth - Style.marginL)) + panelX = Math.max(Style.marginL, Math.min(panelX, root.width - panelWidth - Style.marginL)); } - calculatedX = panelX + calculatedX = panelX; } } else { // Standard anchor positioning if (root.panelAnchorHorizontalCenter) { if (root.barIsVertical) { if (root.barPosition === "left") { - var availableStart = root.barMarginH + Style.barHeight - var availableWidth = root.width - availableStart - calculatedX = availableStart + (availableWidth - panelWidth) / 2 + var availableStart = root.barMarginH + Style.barHeight; + var availableWidth = root.width - availableStart; + calculatedX = availableStart + (availableWidth - panelWidth) / 2; } else if (root.barPosition === "right") { - var availableWidth = root.width - root.barMarginH - Style.barHeight - calculatedX = (availableWidth - panelWidth) / 2 + var availableWidth = root.width - root.barMarginH - Style.barHeight; + calculatedX = (availableWidth - panelWidth) / 2; } else { - calculatedX = (root.width - panelWidth) / 2 + calculatedX = (root.width - panelWidth) / 2; } } else { - calculatedX = (root.width - panelWidth) / 2 + calculatedX = (root.width - panelWidth) / 2; } } else if (root.effectivePanelAnchorRight) { if (allowAttach && root.barIsVertical && root.barPosition === "right") { - var rightBarEdge = root.width - root.barMarginH - Style.barHeight - calculatedX = rightBarEdge - panelWidth + var rightBarEdge = root.width - root.barMarginH - Style.barHeight; + calculatedX = rightBarEdge - panelWidth; } else if (allowAttach) { // Account for corner inset when bar is floating, horizontal, AND panel is on same edge as bar - var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom) + var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom); if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) { - var rightCornerInset = Style.radiusL * 2 - calculatedX = root.width - root.barMarginH - rightCornerInset - panelWidth + var rightCornerInset = Style.radiusL * 2; + calculatedX = root.width - root.barMarginH - rightCornerInset - panelWidth; } else { - calculatedX = root.width - panelWidth + calculatedX = root.width - panelWidth; } } else { - calculatedX = root.width - panelWidth - Style.marginL + calculatedX = root.width - panelWidth - Style.marginL; } } else if (root.effectivePanelAnchorLeft) { if (allowAttach && root.barIsVertical && root.barPosition === "left") { - var leftBarEdge = root.barMarginH + Style.barHeight - calculatedX = leftBarEdge + var leftBarEdge = root.barMarginH + Style.barHeight; + calculatedX = leftBarEdge; } else if (allowAttach) { // Account for corner inset when bar is floating, horizontal, AND panel is on same edge as bar - var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom) + var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom); if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) { - var leftCornerInset = Style.radiusL * 2 - calculatedX = root.barMarginH + leftCornerInset + var leftCornerInset = Style.radiusL * 2; + calculatedX = root.barMarginH + leftCornerInset; } else { - calculatedX = 0 + calculatedX = 0; } } else { - calculatedX = Style.marginL + calculatedX = Style.marginL; } } else { // No explicit anchor: default to centering on bar if (root.barIsVertical) { if (root.barPosition === "left") { - var availableStart = root.barMarginH + Style.barHeight - var availableWidth = root.width - availableStart - Style.marginL - calculatedX = availableStart + (availableWidth - panelWidth) / 2 + var availableStart = root.barMarginH + Style.barHeight; + var availableWidth = root.width - availableStart - Style.marginL; + calculatedX = availableStart + (availableWidth - panelWidth) / 2; } else { - var availableWidth = root.width - root.barMarginH - Style.barHeight - Style.marginL - calculatedX = Style.marginL + (availableWidth - panelWidth) / 2 + var availableWidth = root.width - root.barMarginH - Style.barHeight - Style.marginL; + calculatedX = Style.marginL + (availableWidth - panelWidth) / 2; } } else { if (allowAttach) { - var cornerInset = Style.radiusL + (root.barFloating ? Style.radiusL : 0) - var barLeftEdge = root.barMarginH + cornerInset - var barRightEdge = root.width - root.barMarginH - cornerInset - var centeredX = (root.width - panelWidth) / 2 - calculatedX = Math.max(barLeftEdge, Math.min(centeredX, barRightEdge - panelWidth)) + var cornerInset = Style.radiusL + (root.barFloating ? Style.radiusL : 0); + var barLeftEdge = root.barMarginH + cornerInset; + var barRightEdge = root.width - root.barMarginH - cornerInset; + var centeredX = (root.width - panelWidth) / 2; + calculatedX = Math.max(barLeftEdge, Math.min(centeredX, barRightEdge - panelWidth)); } else { - calculatedX = (root.width - panelWidth) / 2 + calculatedX = (root.width - panelWidth) / 2; } } } @@ -274,76 +273,76 @@ Item { // Edge snapping for X if (allowAttach && !root.barFloating && root.width > 0 && panelWidth > 0) { - var leftEdgePos = root.barMarginH + var leftEdgePos = root.barMarginH; if (root.barPosition === "left") { - leftEdgePos = root.barMarginH + Style.barHeight + leftEdgePos = root.barMarginH + Style.barHeight; } - var rightEdgePos = root.width - root.barMarginH - panelWidth + var rightEdgePos = root.width - root.barMarginH - panelWidth; if (root.barPosition === "right") { - rightEdgePos = root.width - root.barMarginH - Style.barHeight - panelWidth + rightEdgePos = root.width - root.barMarginH - Style.barHeight - panelWidth; } // Only snap to left edge if panel is actually meant to be at left - var shouldSnapToLeft = root.effectivePanelAnchorLeft || (!root.hasExplicitHorizontalAnchor && root.barPosition === "left") + var shouldSnapToLeft = root.effectivePanelAnchorLeft || (!root.hasExplicitHorizontalAnchor && root.barPosition === "left"); // Only snap to right edge if panel is actually meant to be at right - var shouldSnapToRight = root.effectivePanelAnchorRight || (!root.hasExplicitHorizontalAnchor && root.barPosition === "right") + var shouldSnapToRight = root.effectivePanelAnchorRight || (!root.hasExplicitHorizontalAnchor && root.barPosition === "right"); if (shouldSnapToLeft && Math.abs(calculatedX - leftEdgePos) <= root.edgeSnapDistance) { - calculatedX = leftEdgePos + calculatedX = leftEdgePos; } else if (shouldSnapToRight && Math.abs(calculatedX - rightEdgePos) <= root.edgeSnapDistance) { - calculatedX = rightEdgePos + calculatedX = rightEdgePos; } } // ===== Y POSITIONING ===== if (root.useButtonPosition && root.height > 0 && panelHeight > 0) { if (root.barPosition === "top") { - var topBarEdge = root.barMarginV + Style.barHeight + var topBarEdge = root.barMarginV + Style.barHeight; if (allowAttach) { - calculatedY = topBarEdge + calculatedY = topBarEdge; } else { - calculatedY = topBarEdge + Style.marginM + calculatedY = topBarEdge + Style.marginM; } } else if (root.barPosition === "bottom") { - var bottomBarEdge = root.height - root.barMarginV - Style.barHeight + var bottomBarEdge = root.height - root.barMarginV - Style.barHeight; if (allowAttach) { - calculatedY = bottomBarEdge - panelHeight + calculatedY = bottomBarEdge - panelHeight; } else { - calculatedY = bottomBarEdge - panelHeight - Style.marginM + calculatedY = bottomBarEdge - panelHeight - Style.marginM; } } else if (root.barIsVertical) { - var panelY = root.buttonPosition.y + root.buttonHeight / 2 - panelHeight / 2 - var extraPadding = (allowAttach && root.barFloating) ? Style.radiusL : 0 + var panelY = root.buttonPosition.y + root.buttonHeight / 2 - panelHeight / 2; + var extraPadding = (allowAttach && root.barFloating) ? Style.radiusL : 0; if (allowAttach) { - var cornerInset = extraPadding + (root.barFloating ? Style.radiusL : 0) - var barTopEdge = root.barMarginV + cornerInset - var barBottomEdge = root.height - root.barMarginV - cornerInset - panelY = Math.max(barTopEdge, Math.min(panelY, barBottomEdge - panelHeight)) + var cornerInset = extraPadding + (root.barFloating ? Style.radiusL : 0); + var barTopEdge = root.barMarginV + cornerInset; + var barBottomEdge = root.height - root.barMarginV - cornerInset; + panelY = Math.max(barTopEdge, Math.min(panelY, barBottomEdge - panelHeight)); } else { - panelY = Math.max(Style.marginL + extraPadding, Math.min(panelY, root.height - panelHeight - Style.marginL - extraPadding)) + panelY = Math.max(Style.marginL + extraPadding, Math.min(panelY, root.height - panelHeight - Style.marginL - extraPadding)); } - calculatedY = panelY + calculatedY = panelY; } } else { // Standard anchor positioning - var barOffset = 0 + var barOffset = 0; if (!allowAttach) { if (root.barPosition === "top") { - barOffset = root.barMarginV + Style.barHeight + Style.marginM + barOffset = root.barMarginV + Style.barHeight + Style.marginM; } else if (root.barPosition === "bottom") { - barOffset = root.barMarginV + Style.barHeight + Style.marginM + barOffset = root.barMarginV + Style.barHeight + Style.marginM; } } else { if (root.effectivePanelAnchorTop && root.barPosition === "top") { - calculatedY = root.barMarginV + Style.barHeight + calculatedY = root.barMarginV + Style.barHeight; } else if (root.effectivePanelAnchorBottom && root.barPosition === "bottom") { - calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight + calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight; } else if (!root.hasExplicitVerticalAnchor) { if (root.barPosition === "top") { - calculatedY = root.barMarginV + Style.barHeight + calculatedY = root.barMarginV + Style.barHeight; } else if (root.barPosition === "bottom") { - calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight + calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight; } } } @@ -352,57 +351,57 @@ Item { if (root.panelAnchorVerticalCenter) { if (!root.barIsVertical) { if (root.barPosition === "top") { - var availableStart = root.barMarginV + Style.barHeight - var availableHeight = root.height - availableStart - calculatedY = availableStart + (availableHeight - panelHeight) / 2 + var availableStart = root.barMarginV + Style.barHeight; + var availableHeight = root.height - availableStart; + calculatedY = availableStart + (availableHeight - panelHeight) / 2; } else if (root.barPosition === "bottom") { - var availableHeight = root.height - root.barMarginV - Style.barHeight - calculatedY = (availableHeight - panelHeight) / 2 + var availableHeight = root.height - root.barMarginV - Style.barHeight; + calculatedY = (availableHeight - panelHeight) / 2; } else { - calculatedY = (root.height - panelHeight) / 2 + calculatedY = (root.height - panelHeight) / 2; } } else { - calculatedY = (root.height - panelHeight) / 2 + calculatedY = (root.height - panelHeight) / 2; } } else if (root.effectivePanelAnchorTop) { if (allowAttach) { - calculatedY = 0 + calculatedY = 0; } else { - var topBarOffset = (root.barPosition === "top") ? barOffset : 0 - calculatedY = topBarOffset + Style.marginL + var topBarOffset = (root.barPosition === "top") ? barOffset : 0; + calculatedY = topBarOffset + Style.marginL; } } else if (root.effectivePanelAnchorBottom) { if (allowAttach) { - calculatedY = root.height - panelHeight + calculatedY = root.height - panelHeight; } else { - var bottomBarOffset = (root.barPosition === "bottom") ? barOffset : 0 - calculatedY = root.height - panelHeight - bottomBarOffset - Style.marginL + var bottomBarOffset = (root.barPosition === "bottom") ? barOffset : 0; + calculatedY = root.height - panelHeight - bottomBarOffset - Style.marginL; } } else { if (root.barIsVertical) { if (allowAttach) { - var cornerInset = root.barFloating ? Style.radiusL * 2 : 0 - var barTopEdge = root.barMarginV + cornerInset - var barBottomEdge = root.height - root.barMarginV - cornerInset - var centeredY = (root.height - panelHeight) / 2 - calculatedY = Math.max(barTopEdge, Math.min(centeredY, barBottomEdge - panelHeight)) + var cornerInset = root.barFloating ? Style.radiusL * 2 : 0; + var barTopEdge = root.barMarginV + cornerInset; + var barBottomEdge = root.height - root.barMarginV - cornerInset; + var centeredY = (root.height - panelHeight) / 2; + calculatedY = Math.max(barTopEdge, Math.min(centeredY, barBottomEdge - panelHeight)); } else { - calculatedY = (root.height - panelHeight) / 2 + calculatedY = (root.height - panelHeight) / 2; } } else { if (allowAttach && !root.barIsVertical) { if (root.barPosition === "top") { - calculatedY = root.barMarginV + Style.barHeight + calculatedY = root.barMarginV + Style.barHeight; } else if (root.barPosition === "bottom") { - calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight + calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight; } } else { if (root.barPosition === "top") { - calculatedY = barOffset + Style.marginL + calculatedY = barOffset + Style.marginL; } else if (root.barPosition === "bottom") { - calculatedY = Style.marginL + calculatedY = Style.marginL; } else { - calculatedY = Style.marginL + calculatedY = Style.marginL; } } } @@ -412,34 +411,34 @@ Item { // Edge snapping for Y if (allowAttach && !root.barFloating && root.height > 0 && panelHeight > 0) { - var topEdgePos = root.barMarginV + var topEdgePos = root.barMarginV; if (root.barPosition === "top") { - topEdgePos = root.barMarginV + Style.barHeight + topEdgePos = root.barMarginV + Style.barHeight; } - var bottomEdgePos = root.height - root.barMarginV - panelHeight + var bottomEdgePos = root.height - root.barMarginV - panelHeight; if (root.barPosition === "bottom") { - bottomEdgePos = root.height - root.barMarginV - Style.barHeight - panelHeight + bottomEdgePos = root.height - root.barMarginV - Style.barHeight - panelHeight; } // Only snap to top edge if panel is actually meant to be at top - var shouldSnapToTop = root.effectivePanelAnchorTop || (!root.hasExplicitVerticalAnchor && root.barPosition === "top") + var shouldSnapToTop = root.effectivePanelAnchorTop || (!root.hasExplicitVerticalAnchor && root.barPosition === "top"); // Only snap to bottom edge if panel is actually meant to be at bottom - var shouldSnapToBottom = root.effectivePanelAnchorBottom || (!root.hasExplicitVerticalAnchor && root.barPosition === "bottom") + var shouldSnapToBottom = root.effectivePanelAnchorBottom || (!root.hasExplicitVerticalAnchor && root.barPosition === "bottom"); if (shouldSnapToTop && Math.abs(calculatedY - topEdgePos) <= root.edgeSnapDistance) { - calculatedY = topEdgePos + calculatedY = topEdgePos; } else if (shouldSnapToBottom && Math.abs(calculatedY - bottomEdgePos) <= root.edgeSnapDistance) { - calculatedY = bottomEdgePos + calculatedY = bottomEdgePos; } } // Apply calculated positions (set targets for animation) - panelBackground.targetX = calculatedX - panelBackground.targetY = calculatedY + panelBackground.targetX = calculatedX; + panelBackground.targetY = calculatedY; - Logger.d("PanelPlaceholder", "Position calculated:", calculatedX, calculatedY, panelName) - Logger.d("PanelPlaceholder", " Panel size:", panelWidth, "x", panelHeight) + Logger.d("PanelPlaceholder", "Position calculated:", calculatedX, calculatedY, panelName); + Logger.d("PanelPlaceholder", " Panel size:", panelWidth, "x", panelHeight); } // The panel background geometry item @@ -469,35 +468,35 @@ Item { // Animation direction determination (using target position to avoid binding loops) readonly property bool willTouchTopBar: { if (!isPanelVisible) - return false + return false; if (!allowAttachToBar || root.barPosition !== "top" || root.barIsVertical) - return false - var targetTopBarY = root.barMarginV + Style.barHeight - return Math.abs(panelBackground.targetY - targetTopBarY) <= 1 + return false; + var targetTopBarY = root.barMarginV + Style.barHeight; + return Math.abs(panelBackground.targetY - targetTopBarY) <= 1; } readonly property bool willTouchBottomBar: { if (!isPanelVisible) - return false + return false; if (!allowAttachToBar || root.barPosition !== "bottom" || root.barIsVertical) - return false - var targetBottomBarY = root.height - root.barMarginV - Style.barHeight - panelBackground.targetHeight - return Math.abs(panelBackground.targetY - targetBottomBarY) <= 1 + return false; + var targetBottomBarY = root.height - root.barMarginV - Style.barHeight - panelBackground.targetHeight; + return Math.abs(panelBackground.targetY - targetBottomBarY) <= 1; } readonly property bool willTouchLeftBar: { if (!isPanelVisible) - return false + return false; if (!allowAttachToBar || root.barPosition !== "left" || !root.barIsVertical) - return false - var targetLeftBarX = root.barMarginH + Style.barHeight - return Math.abs(panelBackground.targetX - targetLeftBarX) <= 1 + return false; + var targetLeftBarX = root.barMarginH + Style.barHeight; + return Math.abs(panelBackground.targetX - targetLeftBarX) <= 1; } readonly property bool willTouchRightBar: { if (!isPanelVisible) - return false + return false; if (!allowAttachToBar || root.barPosition !== "right" || !root.barIsVertical) - return false - var targetRightBarX = root.width - root.barMarginH - Style.barHeight - panelBackground.targetWidth - return Math.abs(panelBackground.targetX - targetRightBarX) <= 1 + return false; + var targetRightBarX = root.width - root.barMarginH - Style.barHeight - panelBackground.targetWidth; + return Math.abs(panelBackground.targetX - targetRightBarX) <= 1; } readonly property bool willTouchTopEdge: isPanelVisible && allowAttach && panelBackground.targetY <= 1 readonly property bool willTouchBottomEdge: isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1) @@ -506,59 +505,59 @@ Item { readonly property bool isActuallyAttachedToAnyEdge: { if (!isPanelVisible) - return false - return willTouchTopBar || willTouchBottomBar || willTouchLeftBar || willTouchRightBar || willTouchTopEdge || willTouchBottomEdge || willTouchLeftEdge || willTouchRightEdge + return false; + return willTouchTopBar || willTouchBottomBar || willTouchLeftBar || willTouchRightBar || willTouchTopEdge || willTouchBottomEdge || willTouchLeftEdge || willTouchRightEdge; } readonly property bool animateFromTop: { if (!isPanelVisible) - return true + return true; if (willTouchTopBar) - return true + return true; if (willTouchTopEdge && !willTouchTopBar && !willTouchBottomBar && !willTouchLeftBar && !willTouchRightBar) - return true + return true; if (!isActuallyAttachedToAnyEdge) - return true - return false + return true; + return false; } readonly property bool animateFromBottom: { if (!isPanelVisible) - return false + return false; if (willTouchBottomBar) - return true + return true; if (willTouchBottomEdge && !willTouchTopBar && !willTouchBottomBar && !willTouchLeftBar && !willTouchRightBar) - return true - return false + return true; + return false; } readonly property bool animateFromLeft: { if (!isPanelVisible) - return false + return false; if (willTouchTopBar || willTouchBottomBar) - return false + return false; if (willTouchLeftBar) - return true - var touchingTopEdge = isPanelVisible && allowAttach && panelBackground.targetY <= 1 - var touchingBottomEdge = isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1) + return true; + var touchingTopEdge = isPanelVisible && allowAttach && panelBackground.targetY <= 1; + var touchingBottomEdge = isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1); if (touchingTopEdge || touchingBottomEdge) - return false + return false; if (willTouchLeftEdge && !willTouchLeftBar && !willTouchTopBar && !willTouchBottomBar && !willTouchRightBar) - return true - return false + return true; + return false; } readonly property bool animateFromRight: { if (!isPanelVisible) - return false + return false; if (willTouchTopBar || willTouchBottomBar) - return false + return false; if (willTouchRightBar) - return true - var touchingTopEdge = isPanelVisible && allowAttach && panelBackground.targetY <= 1 - var touchingBottomEdge = isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1) + return true; + var touchingTopEdge = isPanelVisible && allowAttach && panelBackground.targetY <= 1; + var touchingBottomEdge = isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1); if (touchingTopEdge || touchingBottomEdge) - return false + return false; if (willTouchRightEdge && !willTouchLeftBar && !willTouchTopBar && !willTouchBottomBar && !willTouchRightBar) - return true - return false + return true; + return false; } readonly property bool shouldAnimateWidth: !shouldAnimateHeight && (animateFromLeft || animateFromRight) @@ -567,17 +566,17 @@ Item { // Current animated width/height readonly property real currentWidth: { if (isClosing && opacityFadeComplete && shouldAnimateWidth) - return 0 + return 0; if (isClosing || isPanelVisible) - return targetWidth - return 0 + return targetWidth; + return 0; } readonly property real currentHeight: { if (isClosing && opacityFadeComplete && shouldAnimateHeight) - return 0 + return 0; if (isClosing || isPanelVisible) - return targetHeight - return 0 + return targetHeight; + return 0; } width: currentWidth @@ -586,28 +585,28 @@ Item { x: { if (animateFromRight) { if (isPanelVisible || isClosing) { - var targetRightEdge = targetX + targetWidth - return targetRightEdge - width + var targetRightEdge = targetX + targetWidth; + return targetRightEdge - width; } } - return targetX + return targetX; } y: { if (animateFromBottom) { if (isPanelVisible || isClosing) { - var targetBottomEdge = targetY + targetHeight - return targetBottomEdge - height + var targetBottomEdge = targetY + targetHeight; + return targetBottomEdge - height; } } - return targetY + return targetY; } Behavior on width { NumberAnimation { duration: { if (!panelBackground.shouldAnimateWidth) - return 0 - return root.isClosing ? Style.animationFast : Style.animationNormal + return 0; + return root.isClosing ? Style.animationFast : Style.animationNormal; } easing.type: Easing.BezierSpline easing.bezierCurve: panelBackground.bezierCurve @@ -618,8 +617,8 @@ Item { NumberAnimation { duration: { if (!panelBackground.shouldAnimateHeight) - return 0 - return root.isClosing ? Style.animationFast : Style.animationNormal + return 0; + return root.isClosing ? Style.animationFast : Style.animationNormal; } easing.type: Easing.BezierSpline easing.bezierCurve: panelBackground.bezierCurve @@ -628,75 +627,75 @@ Item { // Corner states for PanelBackground to read property int topLeftCornerState: { - var barInverted = allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft)) - var barTouchInverted = touchingTopBar || touchingLeftBar - var edgeInverted = allowAttach && (touchingLeftEdge || touchingTopEdge) - var oppositeEdgeInverted = allowAttach && (touchingTopEdge && !root.barIsVertical && root.barPosition !== "top") + var barInverted = allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft)); + var barTouchInverted = touchingTopBar || touchingLeftBar; + var edgeInverted = allowAttach && (touchingLeftEdge || touchingTopEdge); + var oppositeEdgeInverted = allowAttach && (touchingTopEdge && !root.barIsVertical && root.barPosition !== "top"); if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingLeftEdge && touchingTopEdge) - return 0 + return 0; if (touchingLeftEdge) - return 2 + return 2; if (touchingTopEdge) - return 1 - return root.barIsVertical ? 2 : 1 + return 1; + return root.barIsVertical ? 2 : 1; } - return 0 + return 0; } property int topRightCornerState: { - var barInverted = allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight)) - var barTouchInverted = touchingTopBar || touchingRightBar - var edgeInverted = allowAttach && (touchingRightEdge || touchingTopEdge) - var oppositeEdgeInverted = allowAttach && (touchingTopEdge && !root.barIsVertical && root.barPosition !== "top") + var barInverted = allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight)); + var barTouchInverted = touchingTopBar || touchingRightBar; + var edgeInverted = allowAttach && (touchingRightEdge || touchingTopEdge); + var oppositeEdgeInverted = allowAttach && (touchingTopEdge && !root.barIsVertical && root.barPosition !== "top"); if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingRightEdge && touchingTopEdge) - return 0 + return 0; if (touchingRightEdge) - return 2 + return 2; if (touchingTopEdge) - return 1 - return root.barIsVertical ? 2 : 1 + return 1; + return root.barIsVertical ? 2 : 1; } - return 0 + return 0; } property int bottomLeftCornerState: { - var barInverted = allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft)) - var barTouchInverted = touchingBottomBar || touchingLeftBar - var edgeInverted = allowAttach && (touchingLeftEdge || touchingBottomEdge) - var oppositeEdgeInverted = allowAttach && (touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom") + var barInverted = allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft)); + var barTouchInverted = touchingBottomBar || touchingLeftBar; + var edgeInverted = allowAttach && (touchingLeftEdge || touchingBottomEdge); + var oppositeEdgeInverted = allowAttach && (touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom"); if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingLeftEdge && touchingBottomEdge) - return 0 + return 0; if (touchingLeftEdge) - return 2 + return 2; if (touchingBottomEdge) - return 1 - return root.barIsVertical ? 2 : 1 + return 1; + return root.barIsVertical ? 2 : 1; } - return 0 + return 0; } property int bottomRightCornerState: { - var barInverted = allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight)) - var barTouchInverted = touchingBottomBar || touchingRightBar - var edgeInverted = allowAttach && (touchingRightEdge || touchingBottomEdge) - var oppositeEdgeInverted = allowAttach && (touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom") + var barInverted = allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight)); + var barTouchInverted = touchingBottomBar || touchingRightBar; + var edgeInverted = allowAttach && (touchingRightEdge || touchingBottomEdge); + var oppositeEdgeInverted = allowAttach && (touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom"); if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingRightEdge && touchingBottomEdge) - return 0 + return 0; if (touchingRightEdge) - return 2 + return 2; if (touchingBottomEdge) - return 1 - return root.barIsVertical ? 2 : 1 + return 1; + return root.barIsVertical ? 2 : 1; } - return 0 + return 0; } } } diff --git a/Modules/MainScreen/ScreenCorners.qml b/Modules/MainScreen/ScreenCorners.qml index 89dec642..09429ae8 100644 --- a/Modules/MainScreen/ScreenCorners.qml +++ b/Modules/MainScreen/ScreenCorners.qml @@ -2,13 +2,12 @@ import QtQuick import QtQuick.Shapes import qs.Commons - /** - * ScreenCorners - Shape component for rendering screen corners - * - * Renders concave corners at the screen edges to create a rounded screen effect. - * Self-contained Shape component (no shadows). - */ +* ScreenCorners - Shape component for rendering screen corners +* +* Renders concave corners at the screen edges to create a rounded screen effect. +* Self-contained Shape component (no shadows). +*/ Item { id: root diff --git a/Modules/MainScreen/SmartPanel.qml b/Modules/MainScreen/SmartPanel.qml index fda4c738..736eb9df 100644 --- a/Modules/MainScreen/SmartPanel.qml +++ b/Modules/MainScreen/SmartPanel.qml @@ -3,15 +3,14 @@ import Quickshell import qs.Commons import qs.Services.UI - /** - * SmartPanel - Wrapper that creates placeholder + content window - * - * This component is a thin wrapper that maintains backward compatibility - * while splitting panel rendering into: - * 1. PanelPlaceholder (in MainScreen, for background rendering) - * 2. SmartPanelWindow (separate window, for content) - */ +* SmartPanel - Wrapper that creates placeholder + content window +* +* This component is a thin wrapper that maintains backward compatibility +* while splitting panel rendering into: +* 1. PanelPlaceholder (in MainScreen, for background rendering) +* 2. SmartPanelWindow (separate window, for content) +*/ Item { id: root @@ -59,60 +58,74 @@ Item { // Keyboard event handlers - these can be overridden by panel implementations // Note: SmartPanelWindow directly calls these functions via panelWrapper reference - function onEscapePressed() {} - function onTabPressed() {} - function onBackTabPressed() {} - function onUpPressed() {} - function onDownPressed() {} - function onLeftPressed() {} - function onRightPressed() {} - function onReturnPressed() {} - function onHomePressed() {} - function onEndPressed() {} - function onPageUpPressed() {} - function onPageDownPressed() {} - function onCtrlJPressed() {} - function onCtrlKPressed() {} + function onEscapePressed() { + } + function onTabPressed() { + } + function onBackTabPressed() { + } + function onUpPressed() { + } + function onDownPressed() { + } + function onLeftPressed() { + } + function onRightPressed() { + } + function onReturnPressed() { + } + function onHomePressed() { + } + function onEndPressed() { + } + function onPageUpPressed() { + } + function onPageDownPressed() { + } + function onCtrlJPressed() { + } + function onCtrlKPressed() { + } // Public control functions function toggle(buttonItem, buttonName) { // Ensure window is created before toggling if (!root.windowActive) { - root.windowActive = true + root.windowActive = true; Qt.callLater(function () { if (windowLoader.item) { - windowLoader.item.toggle(buttonItem, buttonName) + windowLoader.item.toggle(buttonItem, buttonName); } - }) + }); } else if (windowLoader.item) { - windowLoader.item.toggle(buttonItem, buttonName) + windowLoader.item.toggle(buttonItem, buttonName); } } function open(buttonItem, buttonName) { // Ensure window is created before opening if (!root.windowActive) { - root.windowActive = true + root.windowActive = true; Qt.callLater(function () { if (windowLoader.item) { - windowLoader.item.open(buttonItem, buttonName) + windowLoader.item.open(buttonItem, buttonName); } - }) + }); } else if (windowLoader.item) { - windowLoader.item.open(buttonItem, buttonName) + windowLoader.item.open(buttonItem, buttonName); } } function close() { if (windowLoader.item) { - windowLoader.item.close() + windowLoader.item.close(); } } // Expose setPosition for panels that need to recalculate on settings changes function setPosition() { if (panelPlaceholder) { - panelPlaceholder.setPosition() + panelPlaceholder.setPosition(); } } @@ -157,11 +170,11 @@ Item { // Forward signals onPanelOpened: root.opened() onPanelClosed: { - root.closed() + root.closed(); // Destroy the window after close animation completes Qt.callLater(function () { - root.windowActive = false - }) + root.windowActive = false; + }); } } } @@ -172,9 +185,9 @@ Item { // Use Qt.callLater to ensure objectName is set by parent before registering Qt.callLater(function () { if (!objectName) { - Logger.w("SmartPanel", "Panel created without objectName - PanelService registration may fail") + Logger.w("SmartPanel", "Panel created without objectName - PanelService registration may fail"); } - PanelService.registerPanel(root) - }) + PanelService.registerPanel(root); + }); } } diff --git a/Modules/MainScreen/SmartPanelWindow.qml b/Modules/MainScreen/SmartPanelWindow.qml index 2d8f4266..045c9b82 100644 --- a/Modules/MainScreen/SmartPanelWindow.qml +++ b/Modules/MainScreen/SmartPanelWindow.qml @@ -5,13 +5,12 @@ import qs.Commons import qs.Services.Compositor import qs.Services.UI - /** - * SmartPanelWindow - Separate window for panel content - * - * This component runs in its own window, separate from MainScreen. - * It follows the PanelPlaceholder for positioning and contains the actual panel content. - */ +* SmartPanelWindow - Separate window for panel content +* +* This component runs in its own window, separate from MainScreen. +* It follows the PanelPlaceholder for positioning and contains the actual panel content. +*/ PanelWindow { id: root @@ -63,13 +62,13 @@ PanelWindow { WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.keyboardFocus: { if (!root.isPanelOpen) { - return WlrKeyboardFocus.None + return WlrKeyboardFocus.None; } if (CompositorService.isHyprland) { // Exclusive focus on hyprland is too restrictive. - return WlrKeyboardFocus.OnDemand + return WlrKeyboardFocus.OnDemand; } else { - return root.exclusiveKeyboard ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.OnDemand + return root.exclusiveKeyboard ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.OnDemand; } } @@ -91,95 +90,95 @@ PanelWindow { // Sync state to placeholder onIsPanelVisibleChanged: { - placeholder.isPanelVisible = isPanelVisible + placeholder.isPanelVisible = isPanelVisible; } onIsClosingChanged: { - placeholder.isClosing = isClosing + placeholder.isClosing = isClosing; } onOpacityFadeCompleteChanged: { - placeholder.opacityFadeComplete = opacityFadeComplete + placeholder.opacityFadeComplete = opacityFadeComplete; } // Panel control functions function toggle(buttonItem, buttonName) { if (!isPanelOpen) { - open(buttonItem, buttonName) + open(buttonItem, buttonName); } else { - close() + close(); } } function open(buttonItem, buttonName) { if (!buttonItem && buttonName) { - buttonItem = BarService.lookupWidget(buttonName, placeholder.screen.name) + buttonItem = BarService.lookupWidget(buttonName, placeholder.screen.name); } if (buttonItem) { - placeholder.buttonItem = buttonItem + placeholder.buttonItem = buttonItem; // Map button position to screen coordinates - var buttonPos = buttonItem.mapToItem(null, 0, 0) - placeholder.buttonPosition = Qt.point(buttonPos.x, buttonPos.y) - placeholder.buttonWidth = buttonItem.width - placeholder.buttonHeight = buttonItem.height - placeholder.useButtonPosition = true + var buttonPos = buttonItem.mapToItem(null, 0, 0); + placeholder.buttonPosition = Qt.point(buttonPos.x, buttonPos.y); + placeholder.buttonWidth = buttonItem.width; + placeholder.buttonHeight = buttonItem.height; + placeholder.useButtonPosition = true; } else { // No button provided: reset button position mode - placeholder.buttonItem = null - placeholder.useButtonPosition = false + placeholder.buttonItem = null; + placeholder.useButtonPosition = false; } // Set isPanelOpen to trigger content loading - isPanelOpen = true + isPanelOpen = true; // Notify PanelService - PanelService.willOpenPanel(root) + PanelService.willOpenPanel(root); } function close() { // Start close sequence: fade opacity first - isClosing = true - sizeAnimationComplete = false - closeFinalized = false + isClosing = true; + sizeAnimationComplete = false; + closeFinalized = false; // Stop the open animation timer if it's still running - opacityTrigger.stop() - openWatchdogActive = false - openWatchdogTimer.stop() + opacityTrigger.stop(); + openWatchdogActive = false; + openWatchdogTimer.stop(); // Start close watchdog timer - closeWatchdogActive = true - closeWatchdogTimer.restart() + closeWatchdogActive = true; + closeWatchdogTimer.restart(); // If opacity is already 0, skip directly to size animation if (contentWrapper.opacity === 0.0) { - opacityFadeComplete = true + opacityFadeComplete = true; } else { - opacityFadeComplete = false + opacityFadeComplete = false; } - Logger.d("SmartPanelWindow", "Closing panel", placeholder.panelName) + Logger.d("SmartPanelWindow", "Closing panel", placeholder.panelName); } function finalizeClose() { // Prevent double-finalization if (root.closeFinalized) { - Logger.w("SmartPanelWindow", "finalizeClose called but already finalized - ignoring", placeholder.panelName) - return + Logger.w("SmartPanelWindow", "finalizeClose called but already finalized - ignoring", placeholder.panelName); + return; } // Complete the close sequence after animations finish - root.closeFinalized = true - root.closeWatchdogActive = false - closeWatchdogTimer.stop() + root.closeFinalized = true; + root.closeWatchdogActive = false; + closeWatchdogTimer.stop(); - root.isPanelVisible = false - root.isPanelOpen = false - root.isClosing = false - root.opacityFadeComplete = false - PanelService.closedPanel(root) - panelClosed() + root.isPanelVisible = false; + root.isPanelOpen = false; + root.isClosing = false; + root.opacityFadeComplete = false; + PanelService.closedPanel(root); + panelClosed(); - Logger.d("SmartPanelWindow", "Panel close finalized", placeholder.panelName) + Logger.d("SmartPanelWindow", "Panel close finalized", placeholder.panelName); } // Fullscreen container for click-to-close and content @@ -189,59 +188,59 @@ PanelWindow { // Handle keyboard events directly via Keys handler Keys.onPressed: event => { - Logger.d("SmartPanelWindow", "Key pressed:", event.key, "for panel:", placeholder.panelName) + Logger.d("SmartPanelWindow", "Key pressed:", event.key, "for panel:", placeholder.panelName); if (event.key === Qt.Key_Escape) { - panelWrapper.onEscapePressed() + panelWrapper.onEscapePressed(); if (closeWithEscape) { - root.close() - event.accepted = true + root.close(); + event.accepted = true; } } else if (panelWrapper) { if (event.key === Qt.Key_Up && panelWrapper.onUpPressed) { - panelWrapper.onUpPressed() - event.accepted = true + panelWrapper.onUpPressed(); + event.accepted = true; } else if (event.key === Qt.Key_Down && panelWrapper.onDownPressed) { - panelWrapper.onDownPressed() - event.accepted = true + panelWrapper.onDownPressed(); + event.accepted = true; } else if (event.key === Qt.Key_Left && panelWrapper.onLeftPressed) { - panelWrapper.onLeftPressed() - event.accepted = true + panelWrapper.onLeftPressed(); + event.accepted = true; } else if (event.key === Qt.Key_Right && panelWrapper.onRightPressed) { - panelWrapper.onRightPressed() - event.accepted = true + panelWrapper.onRightPressed(); + event.accepted = true; } else if (event.key === Qt.Key_Tab && panelWrapper.onTabPressed) { - panelWrapper.onTabPressed() - event.accepted = true + panelWrapper.onTabPressed(); + event.accepted = true; } else if (event.key === Qt.Key_Backtab && panelWrapper.onBackTabPressed) { - panelWrapper.onBackTabPressed() - event.accepted = true + panelWrapper.onBackTabPressed(); + event.accepted = true; } else if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && panelWrapper.onReturnPressed) { - panelWrapper.onReturnPressed() - event.accepted = true + panelWrapper.onReturnPressed(); + event.accepted = true; } else if (event.key === Qt.Key_Home && panelWrapper.onHomePressed) { - panelWrapper.onHomePressed() - event.accepted = true + panelWrapper.onHomePressed(); + event.accepted = true; } else if (event.key === Qt.Key_End && panelWrapper.onEndPressed) { - panelWrapper.onEndPressed() - event.accepted = true + panelWrapper.onEndPressed(); + event.accepted = true; } else if (event.key === Qt.Key_PageUp && panelWrapper.onPageUpPressed) { - panelWrapper.onPageUpPressed() - event.accepted = true + panelWrapper.onPageUpPressed(); + event.accepted = true; } else if (event.key === Qt.Key_PageDown && panelWrapper.onPageDownPressed) { - panelWrapper.onPageDownPressed() - event.accepted = true + panelWrapper.onPageDownPressed(); + event.accepted = true; } else if (event.key === Qt.Key_J && (event.modifiers & Qt.ControlModifier) && panelWrapper.onCtrlJPressed) { - panelWrapper.onCtrlJPressed() - event.accepted = true + panelWrapper.onCtrlJPressed(); + event.accepted = true; } else if (event.key === Qt.Key_K && (event.modifiers & Qt.ControlModifier) && panelWrapper.onCtrlKPressed) { - panelWrapper.onCtrlKPressed() - event.accepted = true + panelWrapper.onCtrlKPressed(); + event.accepted = true; } else if (event.key === Qt.Key_N && (event.modifiers & Qt.ControlModifier) && panelWrapper.onCtrlNPressed) { - panelWrapper.onCtrlNPressed() - event.accepted = true + panelWrapper.onCtrlNPressed(); + event.accepted = true; } else if (event.key === Qt.Key_P && (event.modifiers & Qt.ControlModifier) && panelWrapper.onCtrlPPressed) { - panelWrapper.onCtrlPPressed() - event.accepted = true + panelWrapper.onCtrlPPressed(); + event.accepted = true; } } } @@ -252,8 +251,8 @@ PanelWindow { enabled: root.isPanelOpen && !root.isClosing acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton onClicked: mouse => { - root.close() - mouse.accepted = true + root.close(); + mouse.accepted = true; } z: 0 } @@ -271,10 +270,10 @@ PanelWindow { // Opacity animation opacity: { if (isClosing) - return 0.0 + return 0.0; if (isPanelVisible && sizeAnimationComplete) - return 1.0 - return 0.0 + return 1.0; + return 0.0; } Behavior on opacity { @@ -287,33 +286,33 @@ PanelWindow { // Safety: Zero-duration animation handling if (!running && duration === 0) { if (root.isClosing && contentWrapper.opacity === 0.0) { - root.opacityFadeComplete = true - var shouldFinalizeNow = placeholder.panelItem && !placeholder.panelItem.shouldAnimateWidth && !placeholder.panelItem.shouldAnimateHeight + root.opacityFadeComplete = true; + var shouldFinalizeNow = placeholder.panelItem && !placeholder.panelItem.shouldAnimateWidth && !placeholder.panelItem.shouldAnimateHeight; if (shouldFinalizeNow) { - Logger.d("SmartPanelWindow", "Zero-duration opacity + no size animation - finalizing", placeholder.panelName) - Qt.callLater(root.finalizeClose) + Logger.d("SmartPanelWindow", "Zero-duration opacity + no size animation - finalizing", placeholder.panelName); + Qt.callLater(root.finalizeClose); } } else if (root.isPanelVisible && contentWrapper.opacity === 1.0) { - root.openWatchdogActive = false - openWatchdogTimer.stop() + root.openWatchdogActive = false; + openWatchdogTimer.stop(); } - return + return; } // When opacity fade completes during close, trigger size animation if (!running && root.isClosing && contentWrapper.opacity === 0.0) { - root.opacityFadeComplete = true - var shouldFinalizeNow = placeholder.panelItem && !placeholder.panelItem.shouldAnimateWidth && !placeholder.panelItem.shouldAnimateHeight + root.opacityFadeComplete = true; + var shouldFinalizeNow = placeholder.panelItem && !placeholder.panelItem.shouldAnimateWidth && !placeholder.panelItem.shouldAnimateHeight; if (shouldFinalizeNow) { - Logger.d("SmartPanelWindow", "No animation - finalizing immediately", placeholder.panelName) - Qt.callLater(root.finalizeClose) + Logger.d("SmartPanelWindow", "No animation - finalizing immediately", placeholder.panelName); + Qt.callLater(root.finalizeClose); } else { - Logger.d("SmartPanelWindow", "Animation will run - waiting for size animation", placeholder.panelName) + Logger.d("SmartPanelWindow", "Animation will run - waiting for size animation", placeholder.panelName); } } // When opacity fade completes during open, stop watchdog else if (!running && root.isPanelVisible && contentWrapper.opacity === 1.0) { - root.openWatchdogActive = false - openWatchdogTimer.stop() + root.openWatchdogActive = false; + openWatchdogTimer.stop(); } } } @@ -330,31 +329,31 @@ PanelWindow { onLoaded: { // Capture initial content-driven size if available if (contentLoader.item) { - var hasWidthProp = contentLoader.item.hasOwnProperty('contentPreferredWidth') - var hasHeightProp = contentLoader.item.hasOwnProperty('contentPreferredHeight') + var hasWidthProp = contentLoader.item.hasOwnProperty('contentPreferredWidth'); + var hasHeightProp = contentLoader.item.hasOwnProperty('contentPreferredHeight'); if (hasWidthProp || hasHeightProp) { - var initialWidth = hasWidthProp ? contentLoader.item.contentPreferredWidth : 0 - var initialHeight = hasHeightProp ? contentLoader.item.contentPreferredHeight : 0 - placeholder.updateContentSize(initialWidth, initialHeight) - Logger.d("SmartPanelWindow", "Initial content size:", initialWidth, "x", initialHeight, placeholder.panelName) + var initialWidth = hasWidthProp ? contentLoader.item.contentPreferredWidth : 0; + var initialHeight = hasHeightProp ? contentLoader.item.contentPreferredHeight : 0; + placeholder.updateContentSize(initialWidth, initialHeight); + Logger.d("SmartPanelWindow", "Initial content size:", initialWidth, "x", initialHeight, placeholder.panelName); } } // Calculate position in placeholder - placeholder.setPosition() + placeholder.setPosition(); // Make panel visible on the next frame Qt.callLater(function () { - root.isPanelVisible = true - opacityTrigger.start() + root.isPanelVisible = true; + opacityTrigger.start(); // Start open watchdog timer - root.openWatchdogActive = true - openWatchdogTimer.start() + root.openWatchdogActive = true; + openWatchdogTimer.start(); - panelOpened() - }) + panelOpened(); + }); } } @@ -363,7 +362,7 @@ PanelWindow { anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton onClicked: mouse => { - mouse.accepted = true // Eat the click to prevent propagation to background + mouse.accepted = true; // Eat the click to prevent propagation to background } z: -1 // Behind content but above background click-to-close } @@ -375,13 +374,13 @@ PanelWindow { function onContentPreferredWidthChanged() { if (root.isPanelOpen && root.isPanelVisible && contentLoader.item) { - placeholder.updateContentSize(contentLoader.item.contentPreferredWidth, placeholder.contentPreferredHeight) + placeholder.updateContentSize(contentLoader.item.contentPreferredWidth, placeholder.contentPreferredHeight); } } function onContentPreferredHeightChanged() { if (root.isPanelOpen && root.isPanelVisible && contentLoader.item) { - placeholder.updateContentSize(placeholder.contentPreferredWidth, contentLoader.item.contentPreferredHeight) + placeholder.updateContentSize(placeholder.contentPreferredWidth, contentLoader.item.contentPreferredHeight); } } } @@ -395,7 +394,7 @@ PanelWindow { repeat: false onTriggered: { if (root.isPanelVisible) { - root.sizeAnimationComplete = true + root.sizeAnimationComplete = true; } } } @@ -407,11 +406,11 @@ PanelWindow { repeat: false onTriggered: { if (root.openWatchdogActive) { - Logger.w("SmartPanelWindow", "Open watchdog timeout - forcing panel visible state", placeholder.panelName) - root.openWatchdogActive = false + Logger.w("SmartPanelWindow", "Open watchdog timeout - forcing panel visible state", placeholder.panelName); + root.openWatchdogActive = false; if (root.isPanelOpen && !root.isPanelVisible) { - root.isPanelVisible = true - root.sizeAnimationComplete = true + root.isPanelVisible = true; + root.sizeAnimationComplete = true; } } } @@ -424,8 +423,8 @@ PanelWindow { repeat: false onTriggered: { if (root.closeWatchdogActive && !root.closeFinalized) { - Logger.w("SmartPanelWindow", "Close watchdog timeout - forcing panel close", placeholder.panelName) - Qt.callLater(root.finalizeClose) + Logger.w("SmartPanelWindow", "Close watchdog timeout - forcing panel close", placeholder.panelName); + Qt.callLater(root.finalizeClose); } } } @@ -437,14 +436,14 @@ PanelWindow { function onWidthChanged() { // When width shrinks to 0 during close and we're animating width, finalize if (root.isClosing && placeholder.panelItem.width === 0 && placeholder.panelItem.shouldAnimateWidth) { - Qt.callLater(root.finalizeClose) + Qt.callLater(root.finalizeClose); } } function onHeightChanged() { // When height shrinks to 0 during close and we're animating height, finalize if (root.isClosing && placeholder.panelItem.height === 0 && placeholder.panelItem.shouldAnimateHeight) { - Qt.callLater(root.finalizeClose) + Qt.callLater(root.finalizeClose); } } } diff --git a/Modules/MainScreen/TrayMenuWindow.qml b/Modules/MainScreen/TrayMenuWindow.qml index 4625ff7c..1275c088 100644 --- a/Modules/MainScreen/TrayMenuWindow.qml +++ b/Modules/MainScreen/TrayMenuWindow.qml @@ -2,8 +2,8 @@ import QtQuick import Quickshell import Quickshell.Wayland import qs.Commons -import qs.Services.UI import qs.Modules.Bar.Extras +import qs.Services.UI // Separate window for TrayMenu context menus // This is a top-level PanelWindow (sibling to MainScreen, not nested inside it) @@ -30,18 +30,18 @@ PanelWindow { // Register with PanelService so panels can find this window Component.onCompleted: { - objectName = "trayMenuWindow-" + (screen?.name || "unknown") - PanelService.registerTrayMenuWindow(screen, root) + objectName = "trayMenuWindow-" + (screen?.name || "unknown"); + PanelService.registerTrayMenuWindow(screen, root); } function open() { - visible = true + visible = true; } function close() { - visible = false + visible = false; if (trayMenu.item) { - trayMenu.item.hideMenu() + trayMenu.item.hideMenu(); } } @@ -56,7 +56,7 @@ PanelWindow { source: Quickshell.shellDir + "/Modules/Bar/Extras/TrayMenu.qml" onLoaded: { if (item) { - item.screen = root.screen + item.screen = root.screen; } } } diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index f09ef643..8c8eded8 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -2,9 +2,9 @@ import QtQuick import QtQuick.Effects import QtQuick.Layouts import Quickshell -import Quickshell.Widgets -import Quickshell.Wayland import Quickshell.Services.Notifications +import Quickshell.Wayland +import Quickshell.Widgets import qs.Commons import qs.Services.System import qs.Widgets @@ -35,7 +35,7 @@ Variants { target: notificationModel function onCountChanged() { if (notificationModel.count === 0 && root.active) { - delayTimer.restart() + delayTimer.restart(); } } } @@ -66,30 +66,30 @@ Variants { // Calculate bar offsets for each edge separately readonly property int barOffsetTop: { if (barPos !== "top") - return 0 - const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0 - return Style.barHeight + floatMarginV + return 0; + const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0; + return Style.barHeight + floatMarginV; } readonly property int barOffsetBottom: { if (barPos !== "bottom") - return 0 - const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0 - return Style.barHeight + floatMarginV + return 0; + const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0; + return Style.barHeight + floatMarginV; } readonly property int barOffsetLeft: { if (barPos !== "left") - return 0 - const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0 - return floatMarginH + return 0; + const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0; + return floatMarginH; } readonly property int barOffsetRight: { if (barPos !== "right") - return 0 - const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0 - return floatMarginH + return 0; + const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0; + return floatMarginH; } // Anchoring @@ -111,31 +111,31 @@ Variants { Component.onCompleted: { animateConnection = function (notificationId) { - var delegate = null + var delegate = null; if (notificationRepeater) { for (var i = 0; i < notificationRepeater.count; i++) { - var item = notificationRepeater.itemAt(i) + var item = notificationRepeater.itemAt(i); if (item?.notificationId === notificationId) { - delegate = item - break + delegate = item; + break; } } } if (delegate?.animateOut) { - delegate.animateOut() + delegate.animateOut(); } else { - NotificationService.dismissActiveNotification(notificationId) + NotificationService.dismissActiveNotification(notificationId); } - } + }; - NotificationService.animateAndRemove.connect(animateConnection) + NotificationService.animateAndRemove.connect(animateConnection); } Component.onDestruction: { if (animateConnection) { - NotificationService.animateAndRemove.disconnect(animateConnection) - animateConnection = null + NotificationService.animateAndRemove.disconnect(animateConnection); + animateConnection = null; } } @@ -223,8 +223,8 @@ Variants { width: parent.availableWidth * model.progress color: { - var baseColor = model.urgency === 2 ? Color.mError : model.urgency === 0 ? Color.mOnSurface : Color.mPrimary - return Qt.alpha(baseColor, Settings.data.notifications.backgroundOpacity || 1.0) + var baseColor = model.urgency === 2 ? Color.mError : model.urgency === 0 ? Color.mOnSurface : Color.mPrimary; + return Qt.alpha(baseColor, Settings.data.notifications.backgroundOpacity || 1.0); } antialiasing: true @@ -257,10 +257,10 @@ Variants { // Hover handling onHoverCountChanged: { if (hoverCount > 0) { - resumeTimer.stop() - NotificationService.pauseTimeout(notificationId) + resumeTimer.stop(); + NotificationService.pauseTimeout(notificationId); } else { - resumeTimer.start() + resumeTimer.start(); } } @@ -270,7 +270,7 @@ Variants { repeat: false onTriggered: { if (hoverCount === 0) { - NotificationService.resumeTimeout(notificationId) + NotificationService.resumeTimeout(notificationId); } } } @@ -284,30 +284,30 @@ Variants { onExited: parent.hoverCount-- onClicked: { if (mouse.button === Qt.RightButton) { - animateOut() + animateOut(); } } } // Animation setup function triggerEntryAnimation() { - animInDelayTimer.stop() - removalTimer.stop() - resumeTimer.stop() - isRemoving = false - hoverCount = 0 + animInDelayTimer.stop(); + removalTimer.stop(); + resumeTimer.stop(); + isRemoving = false; + hoverCount = 0; if (Settings.data.general.animationDisabled) { - slideOffset = 0 - scaleValue = 1.0 - opacityValue = 1.0 - return + slideOffset = 0; + scaleValue = 1.0; + opacityValue = 1.0; + return; } - slideOffset = slideInOffset - scaleValue = 0.8 - opacityValue = 0.0 - animInDelayTimer.interval = animationDelay - animInDelayTimer.start() + slideOffset = slideInOffset; + scaleValue = 0.8; + opacityValue = 0.0; + animInDelayTimer.interval = animationDelay; + animInDelayTimer.start(); } Component.onCompleted: triggerEntryAnimation() @@ -320,23 +320,23 @@ Variants { repeat: false onTriggered: { if (card.isRemoving) - return - slideOffset = 0 - scaleValue = 1.0 - opacityValue = 1.0 + return; + slideOffset = 0; + scaleValue = 1.0; + opacityValue = 1.0; } } function animateOut() { if (isRemoving) - return - animInDelayTimer.stop() - resumeTimer.stop() - isRemoving = true + return; + animInDelayTimer.stop(); + resumeTimer.stop(); + isRemoving = true; if (!Settings.data.general.animationDisabled) { - slideOffset = slideOutOffset - scaleValue = 0.8 - opacityValue = 0.0 + slideOffset = slideOutOffset; + scaleValue = 0.8; + opacityValue = 0.0; } } @@ -345,13 +345,13 @@ Variants { interval: Style.animationSlow repeat: false onTriggered: { - NotificationService.dismissActiveNotification(notificationId) + NotificationService.dismissActiveNotification(notificationId); } } onIsRemovingChanged: { if (isRemoving) { - removalTimer.start() + removalTimer.start(); } } @@ -478,9 +478,9 @@ Variants { property string parentNotificationId: notificationId property var parsedActions: { try { - return model.actionsJson ? JSON.parse(model.actionsJson) : [] + return model.actionsJson ? JSON.parse(model.actionsJson) : []; } catch (e) { - return [] + return []; } } visible: parsedActions.length > 0 @@ -495,11 +495,11 @@ Variants { onExited: card.hoverCount-- text: { - var actionText = actionData.text || "Open" + var actionText = actionData.text || "Open"; if (actionText.includes(",")) { - return actionText.split(",")[1] || actionText + return actionText.split(",")[1] || actionText; } - return actionText + return actionText; } fontSize: Style.fontSizeS backgroundColor: Color.mPrimary @@ -508,7 +508,7 @@ Variants { outlined: false implicitHeight: 24 onClicked: { - NotificationService.invokeAction(parent.parentNotificationId, actionData.identifier) + NotificationService.invokeAction(parent.parentNotificationId, actionData.identifier); } } } @@ -528,8 +528,8 @@ Variants { anchors.rightMargin: Style.marginXL onClicked: { - NotificationService.removeFromHistory(model.id) - animateOut() + NotificationService.removeFromHistory(model.id); + animateOut(); } } } diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml index 9d0465d2..4cc34cb3 100644 --- a/Modules/OSD/OSD.qml +++ b/Modules/OSD/OSD.qml @@ -1,15 +1,15 @@ import QtQuick import QtQuick.Controls -import QtQuick.Layouts import QtQuick.Effects +import QtQuick.Layouts import Quickshell -import Quickshell.Wayland import Quickshell.Services.Pipewire +import Quickshell.Wayland import qs.Commons -import qs.Widgets import qs.Services.Hardware import qs.Services.Media import qs.Services.System +import qs.Widgets // Unified OSD component that displays volume, input volume, and brightness changes Variants { @@ -52,54 +52,54 @@ Variants { switch (currentOSDType) { case "volume": if (isMuted) - return "volume-mute" + return "volume-mute"; if (currentVolume <= Number.EPSILON) - return "volume-zero" - return currentVolume <= 0.5 ? "volume-low" : "volume-high" + return "volume-zero"; + return currentVolume <= 0.5 ? "volume-low" : "volume-high"; case "inputVolume": - return isInputMuted ? "microphone-off" : "microphone" + return isInputMuted ? "microphone-off" : "microphone"; case "brightness": - return currentBrightness <= 0.5 ? "brightness-low" : "brightness-high" + return currentBrightness <= 0.5 ? "brightness-low" : "brightness-high"; default: - return "" + return ""; } } function getCurrentValue() { switch (currentOSDType) { case "volume": - return isMuted ? 0 : currentVolume + return isMuted ? 0 : currentVolume; case "inputVolume": - return isInputMuted ? 0 : currentInputVolume + return isInputMuted ? 0 : currentInputVolume; case "brightness": - return currentBrightness + return currentBrightness; default: - return 0 + return 0; } } function getMaxValue() { if (currentOSDType === "volume" || currentOSDType === "inputVolume") { - return Settings.data.audio.volumeOverdrive ? 1.5 : 1.0 + return Settings.data.audio.volumeOverdrive ? 1.5 : 1.0; } - return 1.0 + return 1.0; } function getDisplayPercentage() { - const value = getCurrentValue() - const max = getMaxValue() - const pct = Math.round(Math.min(max, value) * 100) - return pct + "%" + const value = getCurrentValue(); + const max = getMaxValue(); + const pct = Math.round(Math.min(max, value) * 100); + return pct + "%"; } function getProgressColor() { - const isMutedState = (currentOSDType === "volume" && isMuted) || (currentOSDType === "inputVolume" && isInputMuted) - return isMutedState ? Color.mError : Color.mPrimary + const isMutedState = (currentOSDType === "volume" && isMuted) || (currentOSDType === "inputVolume" && isInputMuted); + return isMutedState ? Color.mError : Color.mPrimary; } function getIconColor() { - const isMutedState = (currentOSDType === "volume" && isMuted) || (currentOSDType === "inputVolume" && isInputMuted) - return isMutedState ? Color.mError : Color.mOnSurface + const isMutedState = (currentOSDType === "volume" && isMuted) || (currentOSDType === "inputVolume" && isInputMuted); + return isMutedState ? Color.mError : Color.mOnSurface; } // ============================================================================ @@ -108,35 +108,35 @@ Variants { function initializeAudioValues() { // Initialize output volume if (AudioService.sink?.ready && AudioService.sink?.audio && lastKnownVolume < 0) { - const vol = AudioService.volume + const vol = AudioService.volume; if (vol !== undefined && !isNaN(vol)) { - lastKnownVolume = vol - volumeInitialized = true - muteInitialized = true + lastKnownVolume = vol; + volumeInitialized = true; + muteInitialized = true; } } // Initialize input volume if (AudioService.hasInput && AudioService.source?.ready && AudioService.source?.audio && lastKnownInputVolume < 0) { - const inputVol = AudioService.inputVolume + const inputVol = AudioService.inputVolume; if (inputVol !== undefined && !isNaN(inputVol)) { - lastKnownInputVolume = inputVol - inputInitialized = true + lastKnownInputVolume = inputVol; + inputInitialized = true; } } } function resetOutputInit() { - lastKnownVolume = -1 - volumeInitialized = false - muteInitialized = false - Qt.callLater(initializeAudioValues) + lastKnownVolume = -1; + volumeInitialized = false; + muteInitialized = false; + Qt.callLater(initializeAudioValues); } function resetInputInit() { - lastKnownInputVolume = -1 - inputInitialized = false - Qt.callLater(initializeAudioValues) + lastKnownInputVolume = -1; + inputInitialized = false; + Qt.callLater(initializeAudioValues); } // ============================================================================ @@ -144,48 +144,48 @@ Variants { // ============================================================================ function connectBrightnessMonitors() { for (var i = 0; i < BrightnessService.monitors.length; i++) { - const monitor = BrightnessService.monitors[i] - monitor.brightnessUpdated.disconnect(onBrightnessChanged) - monitor.brightnessUpdated.connect(onBrightnessChanged) + const monitor = BrightnessService.monitors[i]; + monitor.brightnessUpdated.disconnect(onBrightnessChanged); + monitor.brightnessUpdated.connect(onBrightnessChanged); } } function onBrightnessChanged(newBrightness) { - lastUpdatedBrightness = newBrightness + lastUpdatedBrightness = newBrightness; if (!brightnessInitialized) { - brightnessInitialized = true - return + brightnessInitialized = true; + return; } - showOSD("brightness") + showOSD("brightness"); } // ============================================================================ // OSD Display Control // ============================================================================ function showOSD(type) { - currentOSDType = type + currentOSDType = type; if (!root.active) { - root.active = true + root.active = true; } if (root.item) { - root.item.showOSD() + root.item.showOSD(); } else { Qt.callLater(() => { if (root.item) - root.item.showOSD() - }) + root.item.showOSD(); + }); } } function hideOSD() { if (root.item?.osdItem) { - root.item.osdItem.hideImmediately() + root.item.osdItem.hideImmediately(); } else if (root.active) { - root.active = false + root.active = false; } } @@ -199,15 +199,15 @@ Variants { function onReadyChanged() { if (Pipewire.ready) - Qt.callLater(initializeAudioValues) + Qt.callLater(initializeAudioValues); } function onDefaultAudioSinkChanged() { - resetOutputInit() + resetOutputInit(); } function onDefaultAudioSourceChanged() { - resetInputInit() + resetInputInit(); } } @@ -217,72 +217,68 @@ Variants { function onSinkChanged() { if (AudioService.sink?.ready && AudioService.sink?.audio) { - resetOutputInit() + resetOutputInit(); } } function onSourceChanged() { if (AudioService.hasInput && AudioService.source?.ready && AudioService.source?.audio) { - resetInputInit() + resetInputInit(); } } function onVolumeChanged() { if (lastKnownVolume < 0) { - initializeAudioValues() + initializeAudioValues(); if (lastKnownVolume < 0) - return + return; } if (!volumeInitialized) - return - + return; if (Math.abs(AudioService.volume - lastKnownVolume) > 0.001) { - lastKnownVolume = AudioService.volume - showOSD("volume") + lastKnownVolume = AudioService.volume; + showOSD("volume"); } } function onMutedChanged() { if (lastKnownVolume < 0) { - initializeAudioValues() + initializeAudioValues(); if (lastKnownVolume < 0) - return + return; } if (!muteInitialized) - return - showOSD("volume") + return; + showOSD("volume"); } function onInputVolumeChanged() { if (!AudioService.hasInput) - return - + return; if (lastKnownInputVolume < 0) { - initializeAudioValues() + initializeAudioValues(); if (lastKnownInputVolume < 0) - return + return; } if (!inputInitialized) - return - + return; if (Math.abs(AudioService.inputVolume - lastKnownInputVolume) > 0.001) { - lastKnownInputVolume = AudioService.inputVolume - showOSD("inputVolume") + lastKnownInputVolume = AudioService.inputVolume; + showOSD("inputVolume"); } } function onInputMutedChanged() { if (!AudioService.hasInput) - return - + return; if (lastKnownInputVolume < 0) { - initializeAudioValues() + initializeAudioValues(); if (lastKnownInputVolume < 0) - return + return; } if (!inputInitialized) - return - showOSD("inputVolume") + return; + showOSD("inputVolume"); } } @@ -290,7 +286,7 @@ Variants { Connections { target: BrightnessService function onMonitorsChanged() { - connectBrightnessMonitors() + connectBrightnessMonitors(); } } @@ -301,9 +297,9 @@ Variants { running: true onTriggered: { if (Pipewire.ready) - initializeAudioValues() - muteInitialized = true - connectBrightnessMonitors() + initializeAudioValues(); + muteInitialized = true; + connectBrightnessMonitors(); } } @@ -314,22 +310,21 @@ Variants { repeat: true onTriggered: { if (!Pipewire.ready) - return - - const needsOutputInit = lastKnownVolume < 0 - const needsInputInit = AudioService.hasInput && lastKnownInputVolume < 0 + return; + const needsOutputInit = lastKnownVolume < 0; + const needsInputInit = AudioService.hasInput && lastKnownInputVolume < 0; if (needsOutputInit || needsInputInit) { - initializeAudioValues() + initializeAudioValues(); // Stop timer if both are initialized - const outputDone = lastKnownVolume >= 0 - const inputDone = !AudioService.hasInput || lastKnownInputVolume >= 0 + const outputDone = lastKnownVolume >= 0; + const inputDone = !AudioService.hasInput || lastKnownInputVolume >= 0; if (outputDone && inputDone) { - running = false + running = false; } } else { - running = false + running = false; } } } @@ -355,8 +350,8 @@ Variants { readonly property int vWidth: Math.round(80 * Style.uiScaleRatio) readonly property int vHeight: Math.round(280 * Style.uiScaleRatio) readonly property int barThickness: { - const base = Math.max(8, Math.round(8 * Style.uiScaleRatio)) - return base % 2 === 0 ? base : base + 1 + const base = Math.max(8, Math.round(8 * Style.uiScaleRatio)); + return base % 2 === 0 ? base : base + 1; } anchors.top: isTop @@ -366,15 +361,15 @@ Variants { function calculateMargin(isAnchored, position) { if (!isAnchored) - return 0 + return 0; - let base = Style.marginM + let base = Style.marginM; if (Settings.data.bar.position === position) { - const isVertical = position === "top" || position === "bottom" - const floatExtra = Settings.data.bar.floating ? (isVertical ? Settings.data.bar.marginVertical : Settings.data.bar.marginHorizontal) * Style.marginXL : 0 - return Style.barHeight + base + floatExtra + const isVertical = position === "top" || position === "bottom"; + const floatExtra = Settings.data.bar.floating ? (isVertical ? Settings.data.bar.marginVertical : Settings.data.bar.marginHorizontal) * Style.marginXL : 0; + return Style.barHeight + base + floatExtra; } - return base + return base; } margins.top: calculateMargin(anchors.top, "top") @@ -389,7 +384,7 @@ Variants { WlrLayershell.namespace: "noctalia-osd-" + (screen?.name || "unknown") WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.layer: Settings.data.osd?.overlayLayer ? WlrLayer.Overlay : WlrLayer.Top - exclusionMode: PanelWindow.ExclusionMode.Ignore + WlrLayershell.exclusionMode: ExclusionMode.Ignore Item { id: osdItem @@ -422,9 +417,9 @@ Variants { id: visibilityTimer interval: Style.animationNormal + 50 onTriggered: { - osdItem.visible = false - root.currentOSDType = "" - root.active = false + osdItem.visible = false; + root.currentOSDType = ""; + root.active = false; } } @@ -436,8 +431,8 @@ Variants { color: Qt.alpha(Color.mSurface, Settings.data.osd.backgroundOpacity || 1.0) border.color: Qt.alpha(Color.mOutline, Settings.data.osd.backgroundOpacity || 1.0) border.width: { - const bw = Math.max(2, Style.borderM) - return bw % 2 === 0 ? bw : bw + 1 + const bw = Math.max(2, Style.borderM); + return bw % 2 === 0 ? bw : bw + 1; } } @@ -608,39 +603,39 @@ Variants { } function show() { - hideTimer.stop() - visibilityTimer.stop() - osdItem.visible = true + hideTimer.stop(); + visibilityTimer.stop(); + osdItem.visible = true; Qt.callLater(() => { - osdItem.opacity = 1 - osdItem.scale = 1.0 - }) + osdItem.opacity = 1; + osdItem.scale = 1.0; + }); - hideTimer.start() + hideTimer.start(); } function hide() { - hideTimer.stop() - visibilityTimer.stop() - osdItem.opacity = 0 - osdItem.scale = 0.85 - visibilityTimer.start() + hideTimer.stop(); + visibilityTimer.stop(); + osdItem.opacity = 0; + osdItem.scale = 0.85; + visibilityTimer.start(); } function hideImmediately() { - hideTimer.stop() - visibilityTimer.stop() - osdItem.opacity = 0 - osdItem.scale = 0.85 - osdItem.visible = false - root.currentOSDType = "" - root.active = false + hideTimer.stop(); + visibilityTimer.stop(); + osdItem.opacity = 0; + osdItem.scale = 0.85; + osdItem.visible = false; + root.currentOSDType = ""; + root.active = false; } } function showOSD() { - osdItem.show() + osdItem.show(); } } } diff --git a/Modules/Panels/Audio/AudioPanel.qml b/Modules/Panels/Audio/AudioPanel.qml index 6d857791..093d433f 100644 --- a/Modules/Panels/Audio/AudioPanel.qml +++ b/Modules/Panels/Audio/AudioPanel.qml @@ -1,12 +1,12 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Services.Pipewire import qs.Commons -import qs.Widgets import qs.Modules.MainScreen import qs.Services.Media +import qs.Widgets SmartPanel { id: root @@ -25,7 +25,7 @@ SmartPanel { target: AudioService.sink?.audio ? AudioService.sink?.audio : null function onVolumeChanged() { if (!localOutputVolumeChanging) { - localOutputVolume = AudioService.volume + localOutputVolume = AudioService.volume; } } } @@ -34,7 +34,7 @@ SmartPanel { target: AudioService.source?.audio ? AudioService.source?.audio : null function onVolumeChanged() { if (!localInputVolumeChanging) { - localInputVolume = AudioService.inputVolume + localInputVolume = AudioService.inputVolume; } } } @@ -46,10 +46,10 @@ SmartPanel { repeat: true onTriggered: { if (Math.abs(localOutputVolume - AudioService.volume) >= 0.01) { - AudioService.setVolume(localOutputVolume) + AudioService.setVolume(localOutputVolume); } if (Math.abs(localInputVolume - AudioService.inputVolume) >= 0.01) { - AudioService.setInputVolume(localInputVolume) + AudioService.setInputVolume(localInputVolume); } } } @@ -95,7 +95,7 @@ SmartPanel { tooltipText: I18n.tr("tooltips.output-muted") baseSize: Style.baseWidgetSize * 0.8 onClicked: { - AudioService.setOutputMuted(!AudioService.muted) + AudioService.setOutputMuted(!AudioService.muted); } } @@ -104,7 +104,7 @@ SmartPanel { tooltipText: I18n.tr("tooltips.input-muted") baseSize: Style.baseWidgetSize * 0.8 onClicked: { - AudioService.setInputMuted(!AudioService.inputMuted) + AudioService.setInputMuted(!AudioService.inputMuted); } } @@ -113,7 +113,7 @@ SmartPanel { tooltipText: I18n.tr("tooltips.close") baseSize: Style.baseWidgetSize * 0.8 onClicked: { - root.close() + root.close(); } } } @@ -179,8 +179,8 @@ SmartPanel { text: modelData.description checked: AudioService.sink?.id === modelData.id onClicked: { - AudioService.setAudioSink(modelData) - localOutputVolume = AudioService.volume + AudioService.setAudioSink(modelData); + localOutputVolume = AudioService.volume; } Layout.fillWidth: true } diff --git a/Modules/Panels/Battery/BatteryPanel.qml b/Modules/Panels/Battery/BatteryPanel.qml deleted file mode 100644 index f9544e26..00000000 --- a/Modules/Panels/Battery/BatteryPanel.qml +++ /dev/null @@ -1,153 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import Quickshell -import Quickshell.Wayland -import qs.Commons -import qs.Services.Hardware -import qs.Widgets -import qs.Modules.MainScreen - -SmartPanel { - id: root - - property var optionsModel: [] - - function updateOptionsModel() { - let newOptions = [{ - "id": BatteryService.ChargingMode.Full, - "label": "battery.panel.full" - }, { - "id": BatteryService.ChargingMode.Balanced, - "label": "battery.panel.balanced" - }, { - "id": BatteryService.ChargingMode.Lifespan, - "label": "battery.panel.lifespan" - }] - root.optionsModel = newOptions - } - - onOpened: { - updateOptionsModel() - } - - ButtonGroup { - id: batteryGroup - } - - Component { - id: optionsComponent - ColumnLayout { - spacing: Style.marginM - Repeater { - model: root.optionsModel - delegate: NRadioButton { - ButtonGroup.group: batteryGroup - required property var modelData - text: I18n.tr(modelData.label, { - "percent": BatteryService.getThresholdValue(modelData.id) - }) - checked: BatteryService.chargingMode === modelData.id - onClicked: { - BatteryService.setChargingMode(modelData.id) - } - Layout.fillWidth: true - } - } - } - } - - Component { - id: disabledComponent - - ColumnLayout { - anchors.centerIn: parent - spacing: Style.marginM - - NIcon { - icon: "recharging" - pointSize: 48 - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: I18n.tr("battery.panel.disabled") - pointSize: Style.fontSizeL - color: Color.mOnSurfaceVariant - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignHCenter - } - } - } - - panelContent: Item { - anchors.fill: parent - - property real contentPreferredWidth: Math.round(340 * Style.uiScaleRatio) - property real contentPreferredHeight: Math.round(mainLayout.implicitHeight + Style.marginM * 2) - - ColumnLayout { - id: mainLayout - anchors.centerIn: parent - width: parent.contentPreferredWidth - Style.marginM * 2 - anchors.margins: Style.marginM - spacing: Style.marginM - - // HEADER - NBox { - Layout.fillWidth: true - Layout.preferredHeight: header.implicitHeight + Style.marginM * 2 - - RowLayout { - id: header - anchors.fill: parent - anchors.margins: Style.marginM - spacing: Style.marginM - - NIcon { - icon: "battery-4" - pointSize: Style.fontSizeXXL - color: Color.mPrimary - } - - NText { - text: I18n.tr("battery.panel.title") - pointSize: Style.fontSizeL - font.weight: Style.fontWeightBold - color: Color.mOnSurface - Layout.fillWidth: true - } - - NToggle { - id: batteryManagerSwitch - checked: BatteryService.chargingMode !== BatteryService.ChargingMode.Disabled - onToggled: checked => BatteryService.toggleEnabled(checked) - baseSize: Style.baseWidgetSize * 0.65 - } - - NIconButton { - icon: "close" - tooltipText: I18n.tr("tooltips.close") - baseSize: Style.baseWidgetSize * 0.8 - onClicked: { - root.close() - } - } - } - } - - NBox { - Layout.fillWidth: true - Layout.preferredHeight: loader.implicitHeight + Style.marginM * 2 - - Loader { - id: loader - anchors.centerIn: parent - width: parent.width - Style.marginM * 2 - sourceComponent: BatteryService.chargingMode === BatteryService.ChargingMode.Disabled ? disabledComponent : optionsComponent - } - } - } - } -} diff --git a/Modules/Panels/Bluetooth/BluetoothDevicesList.qml b/Modules/Panels/Bluetooth/BluetoothDevicesList.qml index 147f1042..087bf11d 100644 --- a/Modules/Panels/Bluetooth/BluetoothDevicesList.qml +++ b/Modules/Panels/Bluetooth/BluetoothDevicesList.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Bluetooth import Quickshell.Wayland @@ -13,9 +13,7 @@ NBox { property string label: "" property string tooltipText: "" - property var model: { - - } + property var model: {} Layout.fillWidth: true Layout.preferredHeight: column.implicitHeight + Style.marginM * 2 @@ -52,10 +50,10 @@ NBox { function getContentColor(defaultColor = Color.mOnSurface) { if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting) - return Color.mPrimary + return Color.mPrimary; if (modelData.blocked) - return Color.mError - return defaultColor + return Color.mError; + return defaultColor; } Layout.fillWidth: true @@ -154,33 +152,33 @@ NBox { fontWeight: Style.fontWeightMedium backgroundColor: { if (device.canDisconnect && !isBusy) { - return Color.mError + return Color.mError; } - return Color.mPrimary + return Color.mPrimary; } tooltipText: root.tooltipText text: { if (modelData.pairing) { - return I18n.tr("bluetooth.panel.pairing") + return I18n.tr("bluetooth.panel.pairing"); } if (modelData.blocked) { - return I18n.tr("bluetooth.panel.blocked") + return I18n.tr("bluetooth.panel.blocked"); } if (modelData.connected) { - return I18n.tr("bluetooth.panel.disconnect") + return I18n.tr("bluetooth.panel.disconnect"); } - return I18n.tr("bluetooth.panel.connect") + return I18n.tr("bluetooth.panel.connect"); } icon: (isBusy ? "busy" : null) onClicked: { if (modelData.connected) { - BluetoothService.disconnectDevice(modelData) + BluetoothService.disconnectDevice(modelData); } else { - BluetoothService.connectDeviceWithTrust(modelData) + BluetoothService.connectDeviceWithTrust(modelData); } } onRightClicked: { - BluetoothService.forgetDevice(modelData) + BluetoothService.forgetDevice(modelData); } } } diff --git a/Modules/Panels/Bluetooth/BluetoothPanel.qml b/Modules/Panels/Bluetooth/BluetoothPanel.qml index d5661867..8c5a1fc9 100644 --- a/Modules/Panels/Bluetooth/BluetoothPanel.qml +++ b/Modules/Panels/Bluetooth/BluetoothPanel.qml @@ -1,13 +1,13 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Bluetooth import qs.Commons -import qs.Services.UI -import qs.Services.Networking -import qs.Widgets import qs.Modules.MainScreen +import qs.Services.Networking +import qs.Services.UI +import qs.Widgets SmartPanel { id: root @@ -65,7 +65,7 @@ SmartPanel { baseSize: Style.baseWidgetSize * 0.8 onClicked: { if (BluetoothService.adapter) { - BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering + BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering; } } } @@ -75,7 +75,7 @@ SmartPanel { tooltipText: I18n.tr("tooltips.close") baseSize: Style.baseWidgetSize * 0.8 onClicked: { - root.close() + root.close(); } } } @@ -143,9 +143,9 @@ SmartPanel { label: I18n.tr("bluetooth.panel.connected-devices") property var items: { if (!BluetoothService.adapter || !Bluetooth.devices) - return [] - var filtered = Bluetooth.devices.values.filter(dev => dev && !dev.blocked && dev.connected) - return BluetoothService.sortDevices(filtered) + return []; + var filtered = Bluetooth.devices.values.filter(dev => dev && !dev.blocked && dev.connected); + return BluetoothService.sortDevices(filtered); } model: items visible: items.length > 0 @@ -158,9 +158,9 @@ SmartPanel { tooltipText: I18n.tr("tooltips.connect-disconnect-devices") property var items: { if (!BluetoothService.adapter || !Bluetooth.devices) - return [] - var filtered = Bluetooth.devices.values.filter(dev => dev && !dev.blocked && !dev.connected && (dev.paired || dev.trusted)) - return BluetoothService.sortDevices(filtered) + return []; + var filtered = Bluetooth.devices.values.filter(dev => dev && !dev.blocked && !dev.connected && (dev.paired || dev.trusted)); + return BluetoothService.sortDevices(filtered); } model: items visible: items.length > 0 @@ -172,9 +172,9 @@ SmartPanel { label: I18n.tr("bluetooth.panel.available-devices") property var items: { if (!BluetoothService.adapter || !Bluetooth.devices) - return [] - var filtered = Bluetooth.devices.values.filter(dev => dev && !dev.blocked && !dev.paired && !dev.trusted) - return BluetoothService.sortDevices(filtered) + return []; + var filtered = Bluetooth.devices.values.filter(dev => dev && !dev.blocked && !dev.paired && !dev.trusted); + return BluetoothService.sortDevices(filtered); } model: items visible: items.length > 0 @@ -187,13 +187,13 @@ SmartPanel { Layout.preferredHeight: columnScanning.implicitHeight + Style.marginM * 2 visible: { if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices) { - return false + return false; } var availableCount = Bluetooth.devices.values.filter(dev => { - return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0) - }).length - return (availableCount === 0) + return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0); + }).length; + return (availableCount === 0); } ColumnLayout { diff --git a/Modules/Panels/Calendar/CalendarPanel.qml b/Modules/Panels/Calendar/CalendarPanel.qml index 8d1bf3ab..b78ceb5f 100644 --- a/Modules/Panels/Calendar/CalendarPanel.qml +++ b/Modules/Panels/Calendar/CalendarPanel.qml @@ -21,22 +21,22 @@ SmartPanel { // Helper function to calculate ISO week number function getISOWeekNumber(date) { - const target = new Date(date.valueOf()) - const dayNr = (date.getDay() + 6) % 7 - target.setDate(target.getDate() - dayNr + 3) - const firstThursday = new Date(target.getFullYear(), 0, 4) - const diff = target - firstThursday - const oneWeek = 1000 * 60 * 60 * 24 * 7 - const weekNumber = 1 + Math.round(diff / oneWeek) - return weekNumber + const target = new Date(date.valueOf()); + const dayNr = (date.getDay() + 6) % 7; + target.setDate(target.getDate() - dayNr + 3); + const firstThursday = new Date(target.getFullYear(), 0, 4); + const diff = target - firstThursday; + const oneWeek = 1000 * 60 * 60 * 24 * 7; + const weekNumber = 1 + Math.round(diff / oneWeek); + return weekNumber; } // Helper function to check if an event is all-day function isAllDayEvent(event) { - const duration = event.end - event.start - const startDate = new Date(event.start * 1000) - const isAtMidnight = startDate.getHours() === 0 && startDate.getMinutes() === 0 - return duration === 86400 && isAtMidnight + const duration = event.end - event.start; + const startDate = new Date(event.start * 1000); + const isAtMidnight = startDate.getHours() === 0 && startDate.getMinutes() === 0; + return duration === 86400 && isAtMidnight; } panelContent: Item { @@ -50,12 +50,12 @@ SmartPanel { property real calendarGridHeight: { // Calculate number of weeks in the calendar grid - const numWeeks = grid.daysModel ? Math.ceil(grid.daysModel.length / 7) : 5 + const numWeeks = grid.daysModel ? Math.ceil(grid.daysModel.length / 7) : 5; // Calendar grid height (dynamic based on number of weeks) - const rowHeight = Style.baseWidgetSize * 0.9 + Style.marginXXS + const rowHeight = Style.baseWidgetSize * 0.9 + Style.marginXXS; - return numWeeks * rowHeight + return numWeeks * rowHeight; } ColumnLayout { id: content @@ -69,17 +69,17 @@ SmartPanel { readonly property bool weatherReady: Settings.data.location.weatherEnabled && (LocationService.data.weather !== null) function checkIsCurrentMonth() { - return (now.getMonth() === grid.month) && (now.getFullYear() === grid.year) + return (now.getMonth() === grid.month) && (now.getFullYear() === grid.year); } Component.onCompleted: { - isCurrentMonth = checkIsCurrentMonth() + isCurrentMonth = checkIsCurrentMonth(); } Connections { target: Time function onNowChanged() { - content.isCurrentMonth = content.checkIsCurrentMonth() + content.isCurrentMonth = content.checkIsCurrentMonth(); } } @@ -87,7 +87,7 @@ SmartPanel { target: I18n function onLanguageChanged() { // Force update of day names when language changes - grid.month = grid.month + grid.month = grid.month; } } @@ -180,11 +180,11 @@ SmartPanel { NText { text: { if (!Settings.data.location.weatherEnabled) - return "" + return ""; if (!content.weatherReady) - return I18n.tr("calendar.weather.loading") - const chunks = Settings.data.location.name.split(",") - return chunks[0] + return I18n.tr("calendar.weather.loading"); + const chunks = Settings.data.location.name.split(","); + return chunks[0]; } pointSize: Style.fontSizeM font.weight: Style.fontWeightMedium @@ -227,11 +227,11 @@ SmartPanel { id: calendar Layout.fillWidth: true Layout.preferredHeight: { - const navigationHeight = Style.baseWidgetSize // Navigation buttons row - const dayNamesHeight = Style.baseWidgetSize * 0.6 // Day names header row - const innerMargins = Style.marginM * 2 // Top and bottom margins inside NBox - const innerSpacing = Style.marginS * 2 // Spacing between nav, dayNames, and grid (2 gaps) - return navigationHeight + dayNamesHeight + calendarGridHeight + innerMargins + innerSpacing + const navigationHeight = Style.baseWidgetSize; // Navigation buttons row + const dayNamesHeight = Style.baseWidgetSize * 0.6; // Day names header row + const innerMargins = Style.marginM * 2; // Top and bottom margins inside NBox + const innerSpacing = Style.marginS * 2; // Spacing between nav, dayNames, and grid (2 gaps) + return navigationHeight + dayNamesHeight + calendarGridHeight + innerMargins + innerSpacing; } Behavior on Layout.preferredWidth { @@ -257,46 +257,46 @@ SmartPanel { NIconButton { icon: "chevron-left" onClicked: { - let newDate = new Date(grid.year, grid.month - 1, 1) - grid.year = newDate.getFullYear() - grid.month = newDate.getMonth() - content.isCurrentMonth = content.checkIsCurrentMonth() - const now = new Date() - const monthStart = new Date(grid.year, grid.month, 1) - const monthEnd = new Date(grid.year, grid.month + 1, 0) + let newDate = new Date(grid.year, grid.month - 1, 1); + grid.year = newDate.getFullYear(); + grid.month = newDate.getMonth(); + content.isCurrentMonth = content.checkIsCurrentMonth(); + const now = new Date(); + const monthStart = new Date(grid.year, grid.month, 1); + const monthEnd = new Date(grid.year, grid.month + 1, 0); - const daysBehind = Math.max(0, Math.ceil((now - monthStart) / (24 * 60 * 60 * 1000))) - const daysAhead = Math.max(0, Math.ceil((monthEnd - now) / (24 * 60 * 60 * 1000))) + const daysBehind = Math.max(0, Math.ceil((now - monthStart) / (24 * 60 * 60 * 1000))); + const daysAhead = Math.max(0, Math.ceil((monthEnd - now) / (24 * 60 * 60 * 1000))); - CalendarService.loadEvents(daysAhead + 30, daysBehind + 30) + CalendarService.loadEvents(daysAhead + 30, daysBehind + 30); } } NIconButton { icon: "calendar" onClicked: { - grid.month = now.getMonth() - grid.year = now.getFullYear() - content.isCurrentMonth = true - CalendarService.loadEvents() + grid.month = now.getMonth(); + grid.year = now.getFullYear(); + content.isCurrentMonth = true; + CalendarService.loadEvents(); } } NIconButton { icon: "chevron-right" onClicked: { - let newDate = new Date(grid.year, grid.month + 1, 1) - grid.year = newDate.getFullYear() - grid.month = newDate.getMonth() - content.isCurrentMonth = content.checkIsCurrentMonth() - const now = new Date() - const monthStart = new Date(grid.year, grid.month, 1) - const monthEnd = new Date(grid.year, grid.month + 1, 0) + let newDate = new Date(grid.year, grid.month + 1, 1); + grid.year = newDate.getFullYear(); + grid.month = newDate.getMonth(); + content.isCurrentMonth = content.checkIsCurrentMonth(); + const now = new Date(); + const monthStart = new Date(grid.year, grid.month, 1); + const monthEnd = new Date(grid.year, grid.month + 1, 0); - const daysBehind = Math.max(0, Math.ceil((now - monthStart) / (24 * 60 * 60 * 1000))) - const daysAhead = Math.max(0, Math.ceil((monthEnd - now) / (24 * 60 * 60 * 1000))) + const daysBehind = Math.max(0, Math.ceil((now - monthStart) / (24 * 60 * 60 * 1000))); + const daysAhead = Math.max(0, Math.ceil((monthEnd - now) / (24 * 60 * 60 * 1000))); - CalendarService.loadEvents(daysAhead + 30, daysBehind + 30) + CalendarService.loadEvents(daysAhead + 30, daysBehind + 30); } } } @@ -324,9 +324,9 @@ SmartPanel { NText { anchors.centerIn: parent text: { - let dayIndex = (content.firstDayOfWeek + index) % 7 - const dayName = I18n.locale.dayName(dayIndex, Locale.ShortFormat) - return dayName.substring(0, 2).toUpperCase() + let dayIndex = (content.firstDayOfWeek + index) % 7; + const dayName = I18n.locale.dayName(dayIndex, Locale.ShortFormat); + return dayName.substring(0, 2).toUpperCase(); } color: Color.mPrimary pointSize: Style.fontSizeS @@ -345,55 +345,55 @@ SmartPanel { // Helper function to check if a date has events function hasEventsOnDate(year, month, day) { if (!CalendarService.available || CalendarService.events.length === 0) - return false + return false; - const targetDate = new Date(year, month, day) - const targetStart = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()).getTime() / 1000 - const targetEnd = targetStart + 86400 // +24 hours + const targetDate = new Date(year, month, day); + const targetStart = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()).getTime() / 1000; + const targetEnd = targetStart + 86400; // +24 hours return CalendarService.events.some(event => { // Check if event starts or overlaps with this day - return (event.start >= targetStart && event.start < targetEnd) || (event.end > targetStart && event.end <= targetEnd) || (event.start < targetStart && event.end > targetEnd) - }) + return (event.start >= targetStart && event.start < targetEnd) || (event.end > targetStart && event.end <= targetEnd) || (event.start < targetStart && event.end > targetEnd); + }); } // Helper function to get events for a specific date function getEventsForDate(year, month, day) { if (!CalendarService.available || CalendarService.events.length === 0) - return [] + return []; - const targetDate = new Date(year, month, day) - const targetStart = Math.floor(new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()).getTime() / 1000) - const targetEnd = targetStart + 86400 // +24 hours + const targetDate = new Date(year, month, day); + const targetStart = Math.floor(new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()).getTime() / 1000); + const targetEnd = targetStart + 86400; // +24 hours return CalendarService.events.filter(event => { - return (event.start >= targetStart && event.start < targetEnd) || (event.end > targetStart && event.end <= targetEnd) || (event.start < targetStart && event.end > targetEnd) - }) + return (event.start >= targetStart && event.start < targetEnd) || (event.end > targetStart && event.end <= targetEnd) || (event.start < targetStart && event.end > targetEnd); + }); } // Helper function to check if an event is multi-day function isMultiDayEvent(event) { if (isAllDayEvent(event)) { - return false + return false; } - const startDate = new Date(event.start * 1000) - const endDate = new Date(event.end * 1000) + const startDate = new Date(event.start * 1000); + const endDate = new Date(event.end * 1000); - const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()) - const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()) + const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()); + const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()); - return startDateOnly.getTime() !== endDateOnly.getTime() + return startDateOnly.getTime() !== endDateOnly.getTime(); } // Helper function to get color for a specific event function getEventColor(event, isToday) { if (isMultiDayEvent(event)) { - return isToday ? Color.mOnSecondary : Color.mTertiary + return isToday ? Color.mOnSecondary : Color.mTertiary; } else if (isAllDayEvent(event)) { - return isToday ? Color.mOnSecondary : Color.mSecondary + return isToday ? Color.mOnSecondary : Color.mSecondary; } else { - return isToday ? Color.mOnSecondary : Color.mPrimary + return isToday ? Color.mOnSecondary : Color.mPrimary; } } @@ -402,9 +402,9 @@ SmartPanel { visible: Settings.data.location.showWeekNumberInCalendar Layout.preferredWidth: visible ? Style.baseWidgetSize * 0.7 : 0 Layout.preferredHeight: { - const numWeeks = weekNumbers ? weekNumbers.length : 5 - const rowHeight = Style.baseWidgetSize * 0.9 + Style.marginXXS - return numWeeks * rowHeight + const numWeeks = weekNumbers ? weekNumbers.length : 5; + const rowHeight = Style.baseWidgetSize * 0.9 + Style.marginXXS; + return numWeeks * rowHeight; } spacing: Style.marginXXS @@ -417,33 +417,33 @@ SmartPanel { property var weekNumbers: { if (!grid.daysModel || grid.daysModel.length === 0) - return [] + return []; - const weeks = [] - const numWeeks = Math.ceil(grid.daysModel.length / 7) + const weeks = []; + const numWeeks = Math.ceil(grid.daysModel.length / 7); for (var i = 0; i < numWeeks; i++) { - const dayIndex = i * 7 + const dayIndex = i * 7; if (dayIndex < grid.daysModel.length) { - const weekDay = grid.daysModel[dayIndex] - const date = new Date(weekDay.year, weekDay.month, weekDay.day) + const weekDay = grid.daysModel[dayIndex]; + const date = new Date(weekDay.year, weekDay.month, weekDay.day); // Get Thursday of this week for ISO week calculation - const firstDayOfWeek = content.firstDayOfWeek - let thursday = new Date(date) + const firstDayOfWeek = content.firstDayOfWeek; + let thursday = new Date(date); if (firstDayOfWeek === 0) { - thursday.setDate(date.getDate() + 4) + thursday.setDate(date.getDate() + 4); } else if (firstDayOfWeek === 1) { - thursday.setDate(date.getDate() + 3) + thursday.setDate(date.getDate() + 3); } else { - let daysToThursday = (4 - firstDayOfWeek + 7) % 7 - thursday.setDate(date.getDate() + daysToThursday) + let daysToThursday = (4 - firstDayOfWeek + 7) % 7; + thursday.setDate(date.getDate() + daysToThursday); } - weeks.push(root.getISOWeekNumber(thursday)) + weeks.push(root.getISOWeekNumber(thursday)); } } - return weeks + return weeks; } Repeater { @@ -466,9 +466,9 @@ SmartPanel { id: grid Layout.fillWidth: true Layout.preferredHeight: { - const numWeeks = daysModel ? Math.ceil(daysModel.length / 7) : 5 - const rowHeight = Style.baseWidgetSize * 0.9 + Style.marginXXS - return numWeeks * rowHeight + const numWeeks = daysModel ? Math.ceil(daysModel.length / 7) : 5; + const rowHeight = Style.baseWidgetSize * 0.9 + Style.marginXXS; + return numWeeks * rowHeight; } columns: 7 columnSpacing: Style.marginXXS @@ -486,51 +486,51 @@ SmartPanel { // Calculate days to display property var daysModel: { - const firstOfMonth = new Date(year, month, 1) - const lastOfMonth = new Date(year, month + 1, 0) - const daysInMonth = lastOfMonth.getDate() + const firstOfMonth = new Date(year, month, 1); + const lastOfMonth = new Date(year, month + 1, 0); + const daysInMonth = lastOfMonth.getDate(); // Get first day of week (0 = Sunday, 1 = Monday, etc.) - const firstDayOfWeek = content.firstDayOfWeek - const firstOfMonthDayOfWeek = firstOfMonth.getDay() + const firstDayOfWeek = content.firstDayOfWeek; + const firstOfMonthDayOfWeek = firstOfMonth.getDay(); // Calculate days before first of month - let daysBefore = (firstOfMonthDayOfWeek - firstDayOfWeek + 7) % 7 + let daysBefore = (firstOfMonthDayOfWeek - firstDayOfWeek + 7) % 7; // Calculate days after last of month to complete the week - const lastOfMonthDayOfWeek = lastOfMonth.getDay() - const daysAfter = (firstDayOfWeek - lastOfMonthDayOfWeek - 1 + 7) % 7 + const lastOfMonthDayOfWeek = lastOfMonth.getDay(); + const daysAfter = (firstDayOfWeek - lastOfMonthDayOfWeek - 1 + 7) % 7; // Build array of day objects - const days = [] - const today = new Date() + const days = []; + const today = new Date(); // Previous month days - const prevMonth = new Date(year, month, 0) - const prevMonthDays = prevMonth.getDate() + const prevMonth = new Date(year, month, 0); + const prevMonthDays = prevMonth.getDate(); for (var i = daysBefore - 1; i >= 0; i--) { - const day = prevMonthDays - i - const date = new Date(year, month - 1, day) + const day = prevMonthDays - i; + const date = new Date(year, month - 1, day); days.push({ "day": day, "month": month - 1, "year": month === 0 ? year - 1 : year, "today": false, "currentMonth": false - }) + }); } // Current month days for (var day = 1; day <= daysInMonth; day++) { - const date = new Date(year, month, day) - const isToday = date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth() && date.getDate() === today.getDate() + const date = new Date(year, month, day); + const isToday = date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth() && date.getDate() === today.getDate(); days.push({ "day": day, "month": month, "year": year, "today": isToday, "currentMonth": true - }) + }); } // Next month days (only if needed to complete the week) @@ -541,10 +541,10 @@ SmartPanel { "year": month === 11 ? year + 1 : year, "today": false, "currentMonth": false - }) + }); } - return days + return days; } Repeater { @@ -566,10 +566,10 @@ SmartPanel { text: modelData.day color: { if (modelData.today) - return Color.mOnSecondary + return Color.mOnSecondary; if (modelData.currentMonth) - return Color.mOnSurface - return Color.mOnSurfaceVariant + return Color.mOnSurface; + return Color.mOnSurfaceVariant; } opacity: modelData.currentMonth ? 1.0 : 0.4 pointSize: Style.fontSizeM @@ -602,35 +602,35 @@ SmartPanel { enabled: Settings.data.location.showCalendarEvents onEntered: { - const events = parent.parent.parent.parent.getEventsForDate(modelData.year, modelData.month, modelData.day) + const events = parent.parent.parent.parent.getEventsForDate(modelData.year, modelData.month, modelData.day); if (events.length > 0) { const summaries = events.map(event => { if (isAllDayEvent(event)) { - return event.summary + return event.summary; } else { // Always format with '0' padding to ensure proper horizontal alignment - const timeFormat = Settings.data.location.use12hourFormat ? "hh:mm AP" : "HH:mm" - const start = new Date(event.start * 1000) - const startFormatted = I18n.locale.toString(start, timeFormat) - const end = new Date(event.end * 1000) - const endFormatted = I18n.locale.toString(end, timeFormat) - return `${startFormatted}-${endFormatted} ${event.summary}` + const timeFormat = Settings.data.location.use12hourFormat ? "hh:mm AP" : "HH:mm"; + const start = new Date(event.start * 1000); + const startFormatted = I18n.locale.toString(start, timeFormat); + const end = new Date(event.end * 1000); + const endFormatted = I18n.locale.toString(end, timeFormat); + return `${startFormatted}-${endFormatted} ${event.summary}`; } - }).join('\n') - TooltipService.show(screen, parent, summaries, "auto", Style.tooltipDelay, Settings.data.ui.fontFixed) + }).join('\n'); + TooltipService.show(screen, parent, summaries, "auto", Style.tooltipDelay, Settings.data.ui.fontFixed); } } onClicked: { - const dateWithSlashes = `${(modelData.month + 1).toString().padStart(2, '0')}/${modelData.day.toString().padStart(2, '0')}/${modelData.year.toString().substring(2)}` + const dateWithSlashes = `${(modelData.month + 1).toString().padStart(2, '0')}/${modelData.day.toString().padStart(2, '0')}/${modelData.year.toString().substring(2)}`; if (ProgramCheckerService.gnomeCalendarAvailable) { - Quickshell.execDetached(["gnome-calendar", "--date", dateWithSlashes]) - root.close() + Quickshell.execDetached(["gnome-calendar", "--date", dateWithSlashes]); + root.close(); } } onExited: { - TooltipService.hide() + TooltipService.hide(); } } diff --git a/Modules/Panels/ControlCenter/Cards/AudioCard.qml b/Modules/Panels/ControlCenter/Cards/AudioCard.qml index 05d8b0ec..e397c395 100644 --- a/Modules/Panels/ControlCenter/Cards/AudioCard.qml +++ b/Modules/Panels/ControlCenter/Cards/AudioCard.qml @@ -16,10 +16,10 @@ NBox { property bool localInputVolumeChanging: false Component.onCompleted: { - var vol = AudioService.volume - localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0 - var inputVol = AudioService.inputVolume - localInputVolume = (inputVol !== undefined && !isNaN(inputVol)) ? inputVol : 0 + var vol = AudioService.volume; + localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0; + var inputVol = AudioService.inputVolume; + localInputVolume = (inputVol !== undefined && !isNaN(inputVol)) ? inputVol : 0; } // Timer to debounce volume changes @@ -29,10 +29,10 @@ NBox { repeat: true onTriggered: { if (Math.abs(localOutputVolume - AudioService.volume) >= 0.01) { - AudioService.setVolume(localOutputVolume) + AudioService.setVolume(localOutputVolume); } if (Math.abs(localInputVolume - AudioService.inputVolume) >= 0.01) { - AudioService.setInputVolume(localInputVolume) + AudioService.setInputVolume(localInputVolume); } } } @@ -42,8 +42,8 @@ NBox { target: AudioService function onVolumeChanged() { if (!localOutputVolumeChanging) { - var vol = AudioService.volume - localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0 + var vol = AudioService.volume; + localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0; } } } @@ -52,8 +52,8 @@ NBox { target: AudioService.sink?.audio ? AudioService.sink?.audio : null function onVolumeChanged() { if (!localOutputVolumeChanging) { - var vol = AudioService.volume - localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0 + var vol = AudioService.volume; + localOutputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0; } } } @@ -62,8 +62,8 @@ NBox { target: AudioService function onInputVolumeChanged() { if (!localInputVolumeChanging) { - var vol = AudioService.inputVolume - localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0 + var vol = AudioService.inputVolume; + localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0; } } } @@ -72,8 +72,8 @@ NBox { target: AudioService.source?.audio ? AudioService.source?.audio : null function onVolumeChanged() { if (!localInputVolumeChanging) { - var vol = AudioService.inputVolume - localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0 + var vol = AudioService.inputVolume; + localInputVolume = (vol !== undefined && !isNaN(vol)) ? vol : 0; } } } @@ -105,7 +105,7 @@ NBox { colorFgHover: Color.mOnHover onClicked: { if (AudioService.sink && AudioService.sink.audio) { - AudioService.sink.audio.muted = !AudioService.muted + AudioService.sink.audio.muted = !AudioService.muted; } } } diff --git a/Modules/Panels/ControlCenter/Cards/MediaCard.qml b/Modules/Panels/ControlCenter/Cards/MediaCard.qml index 502c07f1..adc5515a 100644 --- a/Modules/Panels/ControlCenter/Cards/MediaCard.qml +++ b/Modules/Panels/ControlCenter/Cards/MediaCard.qml @@ -1,7 +1,7 @@ import QtQuick import QtQuick.Controls -import QtQuick.Layouts import QtQuick.Effects +import QtQuick.Layouts import Quickshell import qs.Commons import qs.Services.Media @@ -22,7 +22,7 @@ NBox { target: WallpaperService function onWallpaperChanged(screenName, path) { if (screenName === screen.name) { - wallpaper = path + wallpaper = path; } } } @@ -48,8 +48,8 @@ NBox { // Background image that covers everything Image { - readonly property int dim: Math.round(256 * Style.uiScaleRatio) id: bgImage + readonly property int dim: Math.round(256 * Style.uiScaleRatio) anchors.fill: parent source: MediaService.trackArtUrl || wallpaper sourceSize: Qt.size(dim, dim) @@ -81,13 +81,13 @@ NBox { sourceComponent: { switch (Settings.data.audio.visualizerType) { case "linear": - return linearComponent + return linearComponent; case "mirrored": - return mirroredComponent + return mirroredComponent; case "wave": - return waveComponent + return waveComponent; default: - return null + return null; } } @@ -164,8 +164,8 @@ NBox { cursorShape: Qt.PointingHandCursor onClicked: { - var menuItems = [] - var players = MediaService.getAvailablePlayers() + var menuItems = []; + var players = MediaService.getAvailablePlayers(); for (var i = 0; i < players.length; i++) { menuItems.push({ "label": players[i].identity, @@ -173,10 +173,10 @@ NBox { "icon": "disc", "enabled": true, "visible": true - }) + }); } - playerContextMenu.model = menuItems - playerContextMenu.openAtItem(playerSelectorButton, playerSelectorButton.width - playerContextMenu.width, playerSelectorButton.height) + playerContextMenu.model = menuItems; + playerContextMenu.openAtItem(playerSelectorButton, playerSelectorButton.width - playerContextMenu.width, playerSelectorButton.height); } } @@ -187,9 +187,9 @@ NBox { verticalPolicy: ScrollBar.AlwaysOff onTriggered: function (action) { - var index = parseInt(action) + var index = parseInt(action); if (!isNaN(index)) { - MediaService.switchToPlayer(index) + MediaService.switchToPlayer(index); } } } @@ -276,11 +276,11 @@ NBox { property real seekEpsilon: 0.01 property real progressRatio: { if (!MediaService.currentPlayer || MediaService.trackLength <= 0) - return 0 - const r = MediaService.currentPosition / MediaService.trackLength + return 0; + const r = MediaService.currentPosition / MediaService.trackLength; if (isNaN(r) || !isFinite(r)) - return 0 - return Math.max(0, Math.min(1, r)) + return 0; + return Math.max(0, Math.min(1, r)); } property real effectiveRatio: (MediaService.isSeeking && localSeekRatio >= 0) ? Math.max(0, Math.min(1, localSeekRatio)) : progressRatio @@ -290,10 +290,10 @@ NBox { repeat: false onTriggered: { if (MediaService.isSeeking && progressWrapper.localSeekRatio >= 0) { - const next = Math.max(0, Math.min(1, progressWrapper.localSeekRatio)) + const next = Math.max(0, Math.min(1, progressWrapper.localSeekRatio)); if (progressWrapper.lastSentSeekRatio < 0 || Math.abs(next - progressWrapper.lastSentSeekRatio) >= progressWrapper.seekEpsilon) { - MediaService.seekByRatio(next) - progressWrapper.lastSentSeekRatio = next + MediaService.seekByRatio(next); + progressWrapper.lastSentSeekRatio = next; } } } @@ -310,21 +310,21 @@ NBox { heightRatio: 0.6 onMoved: { - progressWrapper.localSeekRatio = value - seekDebounce.restart() + progressWrapper.localSeekRatio = value; + seekDebounce.restart(); } onPressedChanged: { if (pressed) { - MediaService.isSeeking = true - progressWrapper.localSeekRatio = value - MediaService.seekByRatio(value) - progressWrapper.lastSentSeekRatio = value + MediaService.isSeeking = true; + progressWrapper.localSeekRatio = value; + MediaService.seekByRatio(value); + progressWrapper.lastSentSeekRatio = value; } else { - seekDebounce.stop() - MediaService.seekByRatio(value) - MediaService.isSeeking = false - progressWrapper.localSeekRatio = -1 - progressWrapper.lastSentSeekRatio = -1 + seekDebounce.stop(); + MediaService.seekByRatio(value); + MediaService.isSeeking = false; + progressWrapper.localSeekRatio = -1; + progressWrapper.lastSentSeekRatio = -1; } } } diff --git a/Modules/Panels/ControlCenter/Cards/ProfileCard.qml b/Modules/Panels/ControlCenter/Cards/ProfileCard.qml index a03858f0..99a5a810 100644 --- a/Modules/Panels/ControlCenter/Cards/ProfileCard.qml +++ b/Modules/Panels/ControlCenter/Cards/ProfileCard.qml @@ -61,9 +61,9 @@ NBox { icon: "settings" tooltipText: I18n.tr("tooltips.open-settings") onClicked: { - var panel = PanelService.getPanel("settingsPanel", screen) - panel.requestedTab = SettingsPanel.Tab.General - panel.open() + var panel = PanelService.getPanel("settingsPanel", screen); + panel.requestedTab = SettingsPanel.Tab.General; + panel.open(); } } @@ -71,8 +71,8 @@ NBox { icon: "power" tooltipText: I18n.tr("tooltips.session-menu") onClicked: { - PanelService.getPanel("sessionMenuPanel", screen)?.open() - PanelService.getPanel("controlCenterPanel", screen)?.close() + PanelService.getPanel("sessionMenuPanel", screen)?.open(); + PanelService.getPanel("controlCenterPanel", screen)?.close(); } } @@ -80,7 +80,7 @@ NBox { icon: "close" tooltipText: I18n.tr("tooltips.close") onClicked: { - PanelService.getPanel("controlCenterPanel", screen)?.close() + PanelService.getPanel("controlCenterPanel", screen)?.close(); } } } @@ -102,14 +102,14 @@ NBox { stdout: StdioCollector { onStreamFinished: { - var uptimeSeconds = parseFloat(this.text.trim().split(' ')[0]) - uptimeText = Time.formatVagueHumanReadableDuration(uptimeSeconds) - uptimeProcess.running = false + var uptimeSeconds = parseFloat(this.text.trim().split(' ')[0]); + uptimeText = Time.formatVagueHumanReadableDuration(uptimeSeconds); + uptimeProcess.running = false; } } } function updateSystemInfo() { - uptimeProcess.running = true + uptimeProcess.running = true; } } diff --git a/Modules/Panels/ControlCenter/Cards/ShortcutsCard.qml b/Modules/Panels/ControlCenter/Cards/ShortcutsCard.qml index 91fba4b9..2bb973f1 100644 --- a/Modules/Panels/ControlCenter/Cards/ShortcutsCard.qml +++ b/Modules/Panels/ControlCenter/Cards/ShortcutsCard.qml @@ -3,9 +3,9 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import qs.Commons -import qs.Widgets import qs.Modules.Panels.ControlCenter import qs.Modules.Panels.ControlCenter.Cards +import qs.Widgets RowLayout { Layout.fillWidth: true diff --git a/Modules/Panels/ControlCenter/Cards/SystemMonitorCard.qml b/Modules/Panels/ControlCenter/Cards/SystemMonitorCard.qml index d58cc40a..14632ed2 100644 --- a/Modules/Panels/ControlCenter/Cards/SystemMonitorCard.qml +++ b/Modules/Panels/ControlCenter/Cards/SystemMonitorCard.qml @@ -28,9 +28,11 @@ NBox { height: content.widgetHeight Layout.alignment: Qt.AlignHCenter // Highlight color based on thresholds - fillColor: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor - || Color.mError) : Color.mError) : (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor - || Color.mTertiary) : Color.mTertiary) : Color.mPrimary + fillColor: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError) : (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? ( + Settings.data.systemMonitor.warningColor + || Color.mTertiary) : + Color.mTertiary) : + Color.mPrimary textColor: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuCriticalThreshold) ? Color.mSurfaceVariant : (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface } NCircleStat { @@ -42,9 +44,11 @@ NBox { height: content.widgetHeight Layout.alignment: Qt.AlignHCenter // Highlight color based on thresholds - fillColor: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor - || Color.mError) : Color.mError) : (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor - || Color.mTertiary) : Color.mTertiary) : Color.mPrimary + fillColor: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError) : (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? ( + Settings.data.systemMonitor.warningColor + || Color.mTertiary) : + Color.mTertiary) : + Color.mPrimary textColor: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempCriticalThreshold) ? Color.mSurfaceVariant : (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface } NCircleStat { @@ -55,9 +59,11 @@ NBox { height: content.widgetHeight Layout.alignment: Qt.AlignHCenter // Highlight color based on thresholds - fillColor: (SystemStatService.memPercent > Settings.data.systemMonitor.memCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor - || Color.mError) : Color.mError) : (SystemStatService.memPercent > Settings.data.systemMonitor.memWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor - || Color.mTertiary) : Color.mTertiary) : Color.mPrimary + fillColor: (SystemStatService.memPercent > Settings.data.systemMonitor.memCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError) : (SystemStatService.memPercent > Settings.data.systemMonitor.memWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? ( + Settings.data.systemMonitor.warningColor + || Color.mTertiary) : + Color.mTertiary) : + Color.mPrimary textColor: (SystemStatService.memPercent > Settings.data.systemMonitor.memCriticalThreshold) ? Color.mSurfaceVariant : (SystemStatService.memPercent > Settings.data.systemMonitor.memWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface } NCircleStat { @@ -68,11 +74,12 @@ NBox { height: content.widgetHeight Layout.alignment: Qt.AlignHCenter // Highlight color based on thresholds - fillColor: ((SystemStatService.diskPercents["/"] - ?? 0) > Settings.data.systemMonitor.diskCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor - || Color.mError) : Color.mError) : ((SystemStatService.diskPercents["/"] - ?? 0) > Settings.data.systemMonitor.diskWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor - || Color.mTertiary) : Color.mTertiary) : Color.mPrimary + fillColor: ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError) : ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskWarningThreshold) ? ( + Settings.data.systemMonitor.useCustomColors + ? (Settings.data.systemMonitor.warningColor + || Color.mTertiary) : + Color.mTertiary) : + Color.mPrimary textColor: ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskCriticalThreshold) ? Color.mSurfaceVariant : ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface } } diff --git a/Modules/Panels/ControlCenter/Cards/WeatherCard.qml b/Modules/Panels/ControlCenter/Cards/WeatherCard.qml index 52fcd7bc..9dd1250a 100644 --- a/Modules/Panels/ControlCenter/Cards/WeatherCard.qml +++ b/Modules/Panels/ControlCenter/Cards/WeatherCard.qml @@ -43,8 +43,8 @@ NBox { NText { text: { // Ensure the name is not too long if one had to specify the country - const chunks = Settings.data.location.name.split(",") - return chunks[0] + const chunks = Settings.data.location.name.split(","); + return chunks[0]; } pointSize: Style.fontSizeL font.weight: Style.fontWeightBold @@ -56,16 +56,16 @@ NBox { visible: weatherReady text: { if (!weatherReady) { - return "" + return ""; } - var temp = LocationService.data.weather.current_weather.temperature - var suffix = "C" + var temp = LocationService.data.weather.current_weather.temperature; + var suffix = "C"; if (Settings.data.location.useFahrenheit) { - temp = LocationService.celsiusToFahrenheit(temp) - var suffix = "F" + temp = LocationService.celsiusToFahrenheit(temp); + var suffix = "F"; } - temp = Math.round(temp) - return `${temp}°${suffix}` + temp = Math.round(temp); + return `${temp}°${suffix}`; } pointSize: showLocation ? Style.fontSizeXL : Style.fontSizeXL * 1.6 font.weight: Style.fontWeightBold @@ -103,8 +103,8 @@ NBox { NText { Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter text: { - var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/")) - return I18n.locale.toString(weatherDate, "ddd") + var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/")); + return I18n.locale.toString(weatherDate, "ddd"); } color: Color.mOnSurface } @@ -117,15 +117,15 @@ NBox { NText { Layout.alignment: Qt.AlignHCenter text: { - var max = LocationService.data.weather.daily.temperature_2m_max[index] - var min = LocationService.data.weather.daily.temperature_2m_min[index] + var max = LocationService.data.weather.daily.temperature_2m_max[index]; + var min = LocationService.data.weather.daily.temperature_2m_min[index]; if (Settings.data.location.useFahrenheit) { - max = LocationService.celsiusToFahrenheit(max) - min = LocationService.celsiusToFahrenheit(min) + max = LocationService.celsiusToFahrenheit(max); + min = LocationService.celsiusToFahrenheit(min); } - max = Math.round(max) - min = Math.round(min) - return `${max}°/${min}°` + max = Math.round(max); + min = Math.round(min); + return `${max}°/${min}°`; } pointSize: Style.fontSizeXS color: Color.mOnSurfaceVariant diff --git a/Modules/Panels/ControlCenter/ControlCenterPanel.qml b/Modules/Panels/ControlCenter/ControlCenterPanel.qml index 35c6189a..dab8e821 100644 --- a/Modules/Panels/ControlCenter/ControlCenterPanel.qml +++ b/Modules/Panels/ControlCenter/ControlCenterPanel.qml @@ -17,8 +17,8 @@ SmartPanel { // Check if there's a bar on this screen readonly property bool hasBarOnScreen: { - var monitors = Settings.data.bar.monitors || [] - return monitors.length === 0 || monitors.includes(screen?.name) + var monitors = Settings.data.bar.monitors || []; + return monitors.length === 0 || monitors.includes(screen?.name); } // When position is "close_to_bar_button" but there's no bar, fall back to center @@ -33,39 +33,37 @@ SmartPanel { preferredWidth: Math.round(460 * Style.uiScaleRatio) preferredHeight: { - var height = 0 - var count = 0 + var height = 0; + var count = 0; for (var i = 0; i < Settings.data.controlCenter.cards.length; i++) { - const card = Settings.data.controlCenter.cards[i] + const card = Settings.data.controlCenter.cards[i]; if (!card.enabled) - continue - - const contributes = (card.id !== "weather-card" || Settings.data.location.weatherEnabled) + continue; + const contributes = (card.id !== "weather-card" || Settings.data.location.weatherEnabled); if (!contributes) - continue - - count++ + continue; + count++; switch (card.id) { case "profile-card": - height += profileHeight - break + height += profileHeight; + break; case "shortcuts-card": - height += shortcutsHeight - break + height += shortcutsHeight; + break; case "audio-card": - height += audioHeight - break + height += audioHeight; + break; case "weather-card": - height += weatherHeight - break + height += weatherHeight; + break; case "media-sysmon-card": - height += mediaSysMonHeight - break + height += mediaSysMonHeight; + break; default: - break + break; } } - return height + (count + 1) * Style.marginL + return height + (count + 1) * Style.marginL; } readonly property int profileHeight: Math.round(64 * Style.uiScaleRatio) @@ -77,11 +75,11 @@ SmartPanel { property int weatherHeight: Math.round(210 * Style.uiScaleRatio) onOpened: { - MediaService.autoSwitchingPaused = true + MediaService.autoSwitchingPaused = true; } onClosed: { - MediaService.autoSwitchingPaused = false + MediaService.autoSwitchingPaused = false; } panelContent: Item { @@ -103,31 +101,31 @@ SmartPanel { Layout.preferredHeight: { switch (modelData.id) { case "profile-card": - return profileHeight + return profileHeight; case "shortcuts-card": - return shortcutsHeight + return shortcutsHeight; case "audio-card": - return audioHeight + return audioHeight; case "weather-card": - return weatherHeight + return weatherHeight; case "media-sysmon-card": - return mediaSysMonHeight + return mediaSysMonHeight; default: - return 0 + return 0; } } sourceComponent: { switch (modelData.id) { case "profile-card": - return profileCard + return profileCard; case "shortcuts-card": - return shortcutsCard + return shortcutsCard; case "audio-card": - return audioCard + return audioCard; case "weather-card": - return weatherCard + return weatherCard; case "media-sysmon-card": - return mediaSysMonCard + return mediaSysMonCard; } } } @@ -153,7 +151,7 @@ SmartPanel { id: weatherCard WeatherCard { Component.onCompleted: { - root.weatherHeight = this.height + root.weatherHeight = this.height; } } } diff --git a/Modules/Panels/ControlCenter/ControlCenterWidgetLoader.qml b/Modules/Panels/ControlCenter/ControlCenterWidgetLoader.qml index 0fb3cd8b..c6ababc7 100644 --- a/Modules/Panels/ControlCenter/ControlCenterWidgetLoader.qml +++ b/Modules/Panels/ControlCenter/ControlCenterWidgetLoader.qml @@ -1,7 +1,7 @@ import QtQuick import Quickshell -import qs.Services.UI import qs.Commons +import qs.Services.UI Item { id: root @@ -18,7 +18,7 @@ Item { implicitHeight: getImplicitSize(loader.item, "implicitHeight") function getImplicitSize(item, prop) { - return (item && item.visible) ? item[prop] : 0 + return (item && item.visible) ? item[prop] : 0; } Loader { @@ -29,36 +29,36 @@ Item { onLoaded: { if (!item) - return + return; // Apply properties to loaded widget for (var prop in widgetProps) { if (item.hasOwnProperty(prop)) { - item[prop] = widgetProps[prop] + item[prop] = widgetProps[prop]; } } // Set screen property if (item.hasOwnProperty("screen")) { - item.screen = widgetScreen + item.screen = widgetScreen; } // Call custom onLoaded if it exists if (item.hasOwnProperty("onLoaded")) { - item.onLoaded() + item.onLoaded(); } } Component.onDestruction: { // Explicitly clear references - widgetProps = null + widgetProps = null; } } // Error handling Component.onCompleted: { if (!ControlCenterWidgetRegistry.hasWidget(widgetId)) { - Logger.w("ControlCenterWidgetLoader", "Widget not found in registry:", widgetId) + Logger.w("ControlCenterWidgetLoader", "Widget not found in registry:", widgetId); } } } diff --git a/Modules/Panels/ControlCenter/Widgets/CustomButton.qml b/Modules/Panels/ControlCenter/Widgets/CustomButton.qml index bad214ad..97285df5 100644 --- a/Modules/Panels/ControlCenter/Widgets/CustomButton.qml +++ b/Modules/Panels/ControlCenter/Widgets/CustomButton.qml @@ -33,28 +33,28 @@ Item { function _updatePropertiesFromSettings() { if (!widgetSettings) { - return + return; } - onClickedCommand = widgetSettings.onClicked || "" - onRightClickedCommand = widgetSettings.onRightClicked || "" - onMiddleClickedCommand = widgetSettings.onMiddleClicked || "" - stateChecksJson = widgetSettings.stateChecksJson || "[]" // Populate from widgetSettings + onClickedCommand = widgetSettings.onClicked || ""; + onRightClickedCommand = widgetSettings.onRightClicked || ""; + onMiddleClickedCommand = widgetSettings.onMiddleClicked || ""; + stateChecksJson = widgetSettings.stateChecksJson || "[]"; // Populate from widgetSettings try { - _parsedStateChecks = JSON.parse(stateChecksJson) + _parsedStateChecks = JSON.parse(stateChecksJson); } catch (e) { - console.error("CustomButton: Failed to parse stateChecksJson:", e.message) - _parsedStateChecks = [] + console.error("CustomButton: Failed to parse stateChecksJson:", e.message); + _parsedStateChecks = []; } - generalTooltipText = widgetSettings.generalTooltipText || "Custom Button" - enableOnStateLogic = widgetSettings.enableOnStateLogic || false + generalTooltipText = widgetSettings.generalTooltipText || "Custom Button"; + enableOnStateLogic = widgetSettings.enableOnStateLogic || false; - updateState() + updateState(); } function onWidgetSettingsChanged() { if (widgetSettings) { - _updatePropertiesFromSettings() + _updatePropertiesFromSettings(); } } } @@ -64,16 +64,16 @@ Item { running: false command: _currentStateCheckIndex !== -1 && _parsedStateChecks.length > _currentStateCheckIndex ? ["sh", "-c", _parsedStateChecks[_currentStateCheckIndex].command] : [] onExited: function (exitCode, stdout, stderr) { - var currentCheckItem = _parsedStateChecks[_currentStateCheckIndex] - var currentCommand = currentCheckItem.command + var currentCheckItem = _parsedStateChecks[_currentStateCheckIndex]; + var currentCommand = currentCheckItem.command; if (exitCode === 0) { // Command succeeded, this is the active state - _isHot = true - _activeStateIcon = currentCheckItem.icon || widgetSettings.icon || "heart" + _isHot = true; + _activeStateIcon = currentCheckItem.icon || widgetSettings.icon || "heart"; } else { // Command failed, try next one - _currentStateCheckIndex++ - _checkNextState() + _currentStateCheckIndex++; + _checkNextState(); } } } @@ -85,53 +85,53 @@ Item { repeat: false onTriggered: { if (enableOnStateLogic && _parsedStateChecks.length > 0) { - _currentStateCheckIndex = 0 - _checkNextState() + _currentStateCheckIndex = 0; + _checkNextState(); } else { - _isHot = false - _activeStateIcon = widgetSettings.icon || "heart" + _isHot = false; + _activeStateIcon = widgetSettings.icon || "heart"; } } } function _checkNextState() { if (_currentStateCheckIndex < _parsedStateChecks.length) { - var currentCheckItem = _parsedStateChecks[_currentStateCheckIndex] + var currentCheckItem = _parsedStateChecks[_currentStateCheckIndex]; if (currentCheckItem && currentCheckItem.command) { - stateCheckProcessExecutor.running = true + stateCheckProcessExecutor.running = true; } else { - _currentStateCheckIndex++ - _checkNextState() + _currentStateCheckIndex++; + _checkNextState(); } } else { // All checks failed - _isHot = false - _activeStateIcon = widgetSettings.icon || "heart" + _isHot = false; + _activeStateIcon = widgetSettings.icon || "heart"; } } function updateState() { if (!enableOnStateLogic || _parsedStateChecks.length === 0) { - _isHot = false - _activeStateIcon = widgetSettings.icon || "heart" - return + _isHot = false; + _activeStateIcon = widgetSettings.icon || "heart"; + return; } - stateUpdateTimer.restart() + stateUpdateTimer.restart(); } function _buildTooltipText() { - let tooltip = generalTooltipText + let tooltip = generalTooltipText; if (onClickedCommand) { - tooltip += `\nLeft click: ${onClickedCommand}` + tooltip += `\nLeft click: ${onClickedCommand}`; } if (onRightClickedCommand) { - tooltip += `\nRight click: ${onRightClickedCommand}` + tooltip += `\nRight click: ${onRightClickedCommand}`; } if (onMiddleClickedCommand) { - tooltip += `\nMiddle click: ${onMiddleClickedCommand}` + tooltip += `\nMiddle click: ${onMiddleClickedCommand}`; } - return tooltip + return tooltip; } NIconButtonHot { @@ -141,20 +141,20 @@ Item { tooltipText: _buildTooltipText() onClicked: { if (onClickedCommand) { - Quickshell.execDetached(["sh", "-c", onClickedCommand]) - updateState() + Quickshell.execDetached(["sh", "-c", onClickedCommand]); + updateState(); } } onRightClicked: { if (onRightClickedCommand) { - Quickshell.execDetached(["sh", "-c", onRightClickedCommand]) - updateState() + Quickshell.execDetached(["sh", "-c", onRightClickedCommand]); + updateState(); } } onMiddleClicked: { if (onMiddleClickedCommand) { - Quickshell.execDetached(["sh", "-c", onMiddleClickedCommand]) - updateState() + Quickshell.execDetached(["sh", "-c", onMiddleClickedCommand]); + updateState(); } } } diff --git a/Modules/Panels/ControlCenter/Widgets/NightLight.qml b/Modules/Panels/ControlCenter/Widgets/NightLight.qml index c45f197a..d9cba6ba 100644 --- a/Modules/Panels/ControlCenter/Widgets/NightLight.qml +++ b/Modules/Panels/ControlCenter/Widgets/NightLight.qml @@ -16,19 +16,19 @@ NIconButtonHot { onClicked: { if (!Settings.data.nightLight.enabled) { - Settings.data.nightLight.enabled = true - Settings.data.nightLight.forced = false + Settings.data.nightLight.enabled = true; + Settings.data.nightLight.forced = false; } else if (Settings.data.nightLight.enabled && !Settings.data.nightLight.forced) { - Settings.data.nightLight.forced = true + Settings.data.nightLight.forced = true; } else { - Settings.data.nightLight.enabled = false - Settings.data.nightLight.forced = false + Settings.data.nightLight.enabled = false; + Settings.data.nightLight.forced = false; } } onRightClicked: { - var settingsPanel = PanelService.getPanel("settingsPanel", screen) - settingsPanel.requestedTab = SettingsPanel.Tab.Display - settingsPanel.open() + var settingsPanel = PanelService.getPanel("settingsPanel", screen); + settingsPanel.requestedTab = SettingsPanel.Tab.Display; + settingsPanel.open(); } } diff --git a/Modules/Panels/ControlCenter/Widgets/ScreenRecorder.qml b/Modules/Panels/ControlCenter/Widgets/ScreenRecorder.qml index 0cbfec0d..62490026 100644 --- a/Modules/Panels/ControlCenter/Widgets/ScreenRecorder.qml +++ b/Modules/Panels/ControlCenter/Widgets/ScreenRecorder.qml @@ -14,9 +14,9 @@ NIconButtonHot { hot: ScreenRecorderService.isRecording tooltipText: I18n.tr("quickSettings.screenRecorder.tooltip.action") onClicked: { - ScreenRecorderService.toggleRecording() + ScreenRecorderService.toggleRecording(); if (!ScreenRecorderService.isRecording) { - PanelService.getPanel("controlCenterPanel", screen)?.close + PanelService.getPanel("controlCenterPanel", screen)?.close; } } } diff --git a/Modules/Panels/ControlCenter/Widgets/WiFi.qml b/Modules/Panels/ControlCenter/Widgets/WiFi.qml index fae2b122..d8b165b7 100644 --- a/Modules/Panels/ControlCenter/Widgets/WiFi.qml +++ b/Modules/Panels/ControlCenter/Widgets/WiFi.qml @@ -11,21 +11,21 @@ NIconButtonHot { icon: { try { if (NetworkService.ethernetConnected) { - return NetworkService.internetConnectivity ? "ethernet" : "ethernet-off" + return NetworkService.internetConnectivity ? "ethernet" : "ethernet-off"; } - let connected = false - let signalStrength = 0 + let connected = false; + let signalStrength = 0; for (const net in NetworkService.networks) { if (NetworkService.networks[net].connected) { - connected = true - signalStrength = NetworkService.networks[net].signal - break + connected = true; + signalStrength = NetworkService.networks[net].signal; + break; } } - return connected ? NetworkService.signalIcon(signalStrength, true) : "wifi-off" + return connected ? NetworkService.signalIcon(signalStrength, true) : "wifi-off"; } catch (error) { - Logger.e("Wi-Fi", "Error getting icon:", error) - return "wifi-off" + Logger.e("Wi-Fi", "Error getting icon:", error); + return "wifi-off"; } } diff --git a/Modules/Panels/Launcher/Launcher.qml b/Modules/Panels/Launcher/Launcher.qml index 88d07bb2..ed037b5a 100644 --- a/Modules/Panels/Launcher/Launcher.qml +++ b/Modules/Panels/Launcher/Launcher.qml @@ -3,13 +3,13 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Widgets + +import "Plugins" import qs.Commons import qs.Modules.MainScreen import qs.Services.Keyboard import qs.Widgets -import "Plugins" - SmartPanel { id: root @@ -23,12 +23,12 @@ SmartPanel { readonly property string panelPosition: { if (Settings.data.appLauncher.position === "follow_bar") { if (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") { - return `center_${Settings.data.bar.position}` + return `center_${Settings.data.bar.position}`; } else { - return `${Settings.data.bar.position}_center` + return `${Settings.data.bar.position}_center`; } } else { - return Settings.data.appLauncher.position + return Settings.data.appLauncher.position; } } panelAnchorHorizontalCenter: panelPosition === "center" || panelPosition.endsWith("_center") @@ -55,83 +55,83 @@ SmartPanel { // They are not coming from SmartPanelWindow as they are consumed by the search field before reaching the panel. // They are instead being forwared from the search field NTextInput below. function onTabPressed() { - selectNextWrapped() + selectNextWrapped(); } function onBackTabPressed() { - selectPreviousWrapped() + selectPreviousWrapped(); } function onUpPressed() { - selectPreviousWrapped() + selectPreviousWrapped(); } function onDownPressed() { - selectNextWrapped() + selectNextWrapped(); } function onReturnPressed() { - activate() + activate(); } function onHomePressed() { - selectFirst() + selectFirst(); } function onEndPressed() { - selectLast() + selectLast(); } function onPageUpPressed() { - selectPreviousPage() + selectPreviousPage(); } function onPageDownPressed() { - selectNextPage() + selectNextPage(); } function onCtrlJPressed() { - selectNextWrapped() + selectNextWrapped(); } function onCtrlKPressed() { - selectPreviousWrapped() + selectPreviousWrapped(); } function onCtrlNPressed() { - selectNextWrapped() + selectNextWrapped(); } function onCtrlPPressed() { - selectPreviousWrapped() + selectPreviousWrapped(); } // Public API for plugins function setSearchText(text) { - searchText = text + searchText = text; } // Plugin registration function registerPlugin(plugin) { - plugins.push(plugin) - plugin.launcher = root + plugins.push(plugin); + plugin.launcher = root; if (plugin.init) - plugin.init() + plugin.init(); } // Search handling function updateResults() { - results = [] - activePlugin = null + results = []; + activePlugin = null; // Check for command mode if (searchText.startsWith(">")) { // Find plugin that handles this command for (let plugin of plugins) { if (plugin.handleCommand && plugin.handleCommand(searchText)) { - activePlugin = plugin - results = plugin.getResults(searchText) - break + activePlugin = plugin; + results = plugin.getResults(searchText); + break; } } @@ -139,7 +139,7 @@ SmartPanel { if (searchText === ">" && !activePlugin) { for (let plugin of plugins) { if (plugin.commands) { - results = results.concat(plugin.commands()) + results = results.concat(plugin.commands()); } } } @@ -147,43 +147,43 @@ SmartPanel { // Regular search - let plugins contribute results for (let plugin of plugins) { if (plugin.handleSearch) { - const pluginResults = plugin.getResults(searchText) - results = results.concat(pluginResults) + const pluginResults = plugin.getResults(searchText); + results = results.concat(pluginResults); } } } - selectedIndex = 0 + selectedIndex = 0; } onSearchTextChanged: updateResults() // Lifecycle onOpened: { - resultsReady = false - ignoreMouseHover = true + resultsReady = false; + ignoreMouseHover = true; // Notify plugins and update results // Use Qt.callLater to ensure plugins are registered (Component.onCompleted runs first) Qt.callLater(() => { for (let plugin of plugins) { if (plugin.onOpened) - plugin.onOpened() + plugin.onOpened(); } - updateResults() - resultsReady = true - }) + updateResults(); + resultsReady = true; + }); } onClosed: { // Reset search text - searchText = "" - ignoreMouseHover = true + searchText = ""; + ignoreMouseHover = true; // Notify plugins for (let plugin of plugins) { if (plugin.onClosed) - plugin.onClosed() + plugin.onClosed(); } } @@ -191,16 +191,16 @@ SmartPanel { ApplicationsPlugin { id: appsPlugin Component.onCompleted: { - registerPlugin(this) - Logger.d("Launcher", "Registered: ApplicationsPlugin") + registerPlugin(this); + Logger.d("Launcher", "Registered: ApplicationsPlugin"); } } CalculatorPlugin { id: calcPlugin Component.onCompleted: { - registerPlugin(this) - Logger.d("Launcher", "Registered: CalculatorPlugin") + registerPlugin(this); + Logger.d("Launcher", "Registered: CalculatorPlugin"); } } @@ -208,8 +208,8 @@ SmartPanel { id: clipPlugin Component.onCompleted: { if (Settings.data.appLauncher.enableClipboardHistory) { - registerPlugin(this) - Logger.d("Launcher", "Registered: ClipboardPlugin") + registerPlugin(this); + Logger.d("Launcher", "Registered: ClipboardPlugin"); } } } @@ -217,47 +217,47 @@ SmartPanel { // Navigation functions function selectNextWrapped() { if (results.length > 0) { - selectedIndex = (selectedIndex + 1) % results.length + selectedIndex = (selectedIndex + 1) % results.length; } } function selectPreviousWrapped() { if (results.length > 0) { - selectedIndex = (((selectedIndex - 1) % results.length) + results.length) % results.length + selectedIndex = (((selectedIndex - 1) % results.length) + results.length) % results.length; } } function selectFirst() { - selectedIndex = 0 + selectedIndex = 0; } function selectLast() { if (results.length > 0) { - selectedIndex = results.length - 1 + selectedIndex = results.length - 1; } else { - selectedIndex = 0 + selectedIndex = 0; } } function selectNextPage() { if (results.length > 0) { - const page = Math.max(1, Math.floor(600 / entryHeight)) // Use approximate height - selectedIndex = Math.min(selectedIndex + page, results.length - 1) + const page = Math.max(1, Math.floor(600 / entryHeight)); // Use approximate height + selectedIndex = Math.min(selectedIndex + page, results.length - 1); } } function selectPreviousPage() { if (results.length > 0) { - const page = Math.max(1, Math.floor(600 / entryHeight)) // Use approximate height - selectedIndex = Math.max(selectedIndex - page, 0) + const page = Math.max(1, Math.floor(600 / entryHeight)); // Use approximate height + selectedIndex = Math.max(selectedIndex - page, 0); } } function activate() { if (results.length > 0 && results[selectedIndex]) { - const item = results[selectedIndex] + const item = results[selectedIndex]; if (item.onActivate) { - item.onActivate() + item.onActivate(); } } } @@ -284,19 +284,19 @@ SmartPanel { onPositionChanged: mouse => { // Store initial position if (!initialized) { - lastX = mouse.x - lastY = mouse.y - initialized = true - return + lastX = mouse.x; + lastY = mouse.y; + initialized = true; + return; } // Check if mouse actually moved - const deltaX = Math.abs(mouse.x - lastX) - const deltaY = Math.abs(mouse.y - lastY) + const deltaX = Math.abs(mouse.x - lastX); + const deltaY = Math.abs(mouse.y - lastY); if (deltaX > 1 || deltaY > 1) { - root.ignoreMouseHover = false - lastX = mouse.x - lastY = mouse.y + root.ignoreMouseHover = false; + lastX = mouse.x; + lastY = mouse.y; } } @@ -304,7 +304,7 @@ SmartPanel { Connections { target: root function onOpened() { - mouseMovementDetector.initialized = false + mouseMovementDetector.initialized = false; } } } @@ -316,9 +316,9 @@ SmartPanel { // Delay focus to ensure window has keyboard focus Qt.callLater(() => { if (searchInput.inputItem) { - searchInput.inputItem.forceActiveFocus() + searchInput.inputItem.forceActiveFocus(); } - }) + }); } } @@ -348,17 +348,17 @@ SmartPanel { Component.onCompleted: { if (searchInput.inputItem) { - searchInput.inputItem.forceActiveFocus() + searchInput.inputItem.forceActiveFocus(); // Intercept Tab keys before TextField handles them searchInput.inputItem.Keys.onPressed.connect(function (event) { if (event.key === Qt.Key_Tab) { - root.onTabPressed() - event.accepted = true + root.onTabPressed(); + event.accepted = true; } else if (event.key === Qt.Key_Backtab) { - root.onBackTabPressed() - event.accepted = true + root.onBackTabPressed(); + event.accepted = true; } - }) + }); } } } @@ -377,14 +377,12 @@ SmartPanel { currentIndex: selectedIndex cacheBuffer: resultsList.height * 2 onCurrentIndexChanged: { - cancelFlick() + cancelFlick(); if (currentIndex >= 0) { - positionViewAtIndex(currentIndex, ListView.Contain) + positionViewAtIndex(currentIndex, ListView.Contain); } } - onModelChanged: { - - } + onModelChanged: {} delegate: Rectangle { id: entry @@ -396,19 +394,19 @@ SmartPanel { // Pin helpers function togglePin(appId) { if (!appId) - return - let arr = (Settings.data.dock.pinnedApps || []).slice() - const idx = arr.indexOf(appId) + return; + let arr = (Settings.data.dock.pinnedApps || []).slice(); + const idx = arr.indexOf(appId); if (idx >= 0) - arr.splice(idx, 1) + arr.splice(idx, 1); else - arr.push(appId) - Settings.data.dock.pinnedApps = arr + arr.push(appId); + Settings.data.dock.pinnedApps = arr; } function isPinned(appId) { - const arr = Settings.data.dock.pinnedApps || [] - return appId && arr.indexOf(appId) >= 0 + const arr = Settings.data.dock.pinnedApps || []; + return appId && arr.indexOf(appId) >= 0; } // Property to reliably track the current item's ID. @@ -419,7 +417,7 @@ SmartPanel { onCurrentClipboardIdChanged: { // Check if it's a valid ID and if the data isn't already cached. if (currentClipboardId && !ClipboardService.getImageData(currentClipboardId)) { - ClipboardService.decodeToDataUrl(currentClipboardId, modelData.mime, null) + ClipboardService.decodeToDataUrl(currentClipboardId, modelData.mime, null); } } @@ -466,8 +464,8 @@ SmartPanel { // Fetches from the service's cache. // The dependency on `_rev` ensures this binding is re-evaluated when the cache is updated. imagePath: { - _rev - return ClipboardService.getImageData(modelData.clipboardId) || "" + _rev; + return ClipboardService.getImageData(modelData.clipboardId) || ""; } // Loading indicator @@ -487,8 +485,8 @@ SmartPanel { // Error fallback onStatusChanged: status => { if (status === Image.Error) { - iconLoader.visible = true - imagePreview.visible = false + iconLoader.visible = true; + imagePreview.visible = false; } } } @@ -538,10 +536,10 @@ SmartPanel { anchors.centerIn: parent text: { if (!modelData.isImage) - return "" - const desc = modelData.description || "" - const parts = desc.split(" • ") - return parts[0] || "IMG" + return ""; + const desc = modelData.description || ""; + const parts = desc.split(" • "); + return parts[0] || "IMG"; } pointSize: Style.fontSizeXXS color: Color.mPrimary @@ -592,14 +590,14 @@ SmartPanel { cursorShape: Qt.PointingHandCursor onEntered: { if (!root.ignoreMouseHover) { - selectedIndex = index + selectedIndex = index; } } onClicked: mouse => { if (mouse.button === Qt.LeftButton) { - selectedIndex = index - root.activate() - mouse.accepted = true + selectedIndex = index; + root.activate(); + mouse.accepted = true; } } acceptedButtons: Qt.LeftButton @@ -616,9 +614,9 @@ SmartPanel { Layout.fillWidth: true text: { if (results.length === 0) - return searchText ? "No results" : "" - const prefix = activePlugin?.name ? `${activePlugin.name}: ` : "" - return prefix + `${results.length} result${results.length !== 1 ? 's' : ''}` + return searchText ? "No results" : ""; + const prefix = activePlugin?.name ? `${activePlugin.name}: ` : ""; + return prefix + `${results.length} result${results.length !== 1 ? 's' : ''}`; } pointSize: Style.fontSizeXS color: Color.mOnSurfaceVariant diff --git a/Modules/Panels/Launcher/Plugins/ApplicationsPlugin.qml b/Modules/Panels/Launcher/Plugins/ApplicationsPlugin.qml index 3d3a1e60..7b45515d 100644 --- a/Modules/Panels/Launcher/Plugins/ApplicationsPlugin.qml +++ b/Modules/Panels/Launcher/Plugins/ApplicationsPlugin.qml @@ -1,8 +1,8 @@ import QtQuick import Quickshell import Quickshell.Io -import qs.Commons import "../../../../Helpers/FuzzySort.js" as Fuzzysort +import qs.Commons Item { property var launcher: null @@ -29,7 +29,7 @@ Item { onLoadFailed: function (error) { if (error.toString().includes("No such file") || error === 2) { - writeAdapter() + writeAdapter(); } } @@ -43,89 +43,89 @@ Item { } function init() { - loadApplications() + loadApplications(); } function onOpened() { // Refresh apps when launcher opens - loadApplications() + loadApplications(); } function loadApplications() { if (typeof DesktopEntries === 'undefined') { - Logger.w("ApplicationsPlugin", "DesktopEntries service not available") - return + Logger.w("ApplicationsPlugin", "DesktopEntries service not available"); + return; } - const allApps = DesktopEntries.applications.values || [] + const allApps = DesktopEntries.applications.values || []; entries = allApps.filter(app => app && !app.noDisplay).map(app => { // Add executable name property for search - app.executableName = getExecutableName(app) - return app - }) - Logger.d("ApplicationsPlugin", `Loaded ${entries.length} applications`) + app.executableName = getExecutableName(app); + return app; + }); + Logger.d("ApplicationsPlugin", `Loaded ${entries.length} applications`); } function getExecutableName(app) { if (!app) - return "" + return ""; // Try to get executable name from command array if (app.command && Array.isArray(app.command) && app.command.length > 0) { - const cmd = app.command[0] + const cmd = app.command[0]; // Extract just the executable name from the full path - const parts = cmd.split('/') - const executable = parts[parts.length - 1] + const parts = cmd.split('/'); + const executable = parts[parts.length - 1]; // Remove any arguments or parameters - return executable.split(' ')[0] + return executable.split(' ')[0]; } // Try to get from exec property if available if (app.exec) { - const parts = app.exec.split('/') - const executable = parts[parts.length - 1] - return executable.split(' ')[0] + const parts = app.exec.split('/'); + const executable = parts[parts.length - 1]; + return executable.split(' ')[0]; } // Fallback to app id (desktop file name without .desktop) if (app.id) { - return app.id.replace('.desktop', '') + return app.id.replace('.desktop', ''); } - return "" + return ""; } function getResults(query) { if (!entries || entries.length === 0) - return [] + return []; if (!query || query.trim() === "") { // Return all apps, optionally sorted by usage - const favoriteApps = Settings.data.appLauncher.favoriteApps || [] - let sorted + const favoriteApps = Settings.data.appLauncher.favoriteApps || []; + let sorted; if (Settings.data.appLauncher.sortByMostUsed) { sorted = entries.slice().sort((a, b) => { // Favorites first - const aFav = favoriteApps.includes(getAppKey(a)) - const bFav = favoriteApps.includes(getAppKey(b)) + const aFav = favoriteApps.includes(getAppKey(a)); + const bFav = favoriteApps.includes(getAppKey(b)); if (aFav !== bFav) - return aFav ? -1 : 1 - const ua = getUsageCount(a) - const ub = getUsageCount(b) + return aFav ? -1 : 1; + const ua = getUsageCount(a); + const ub = getUsageCount(b); if (ub !== ua) - return ub - ua - return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()) - }) + return ub - ua; + return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()); + }); } else { sorted = entries.slice().sort((a, b) => { - const aFav = favoriteApps.includes(getAppKey(a)) - const bFav = favoriteApps.includes(getAppKey(b)) + const aFav = favoriteApps.includes(getAppKey(a)); + const bFav = favoriteApps.includes(getAppKey(b)); if (aFav !== bFav) - return aFav ? -1 : 1 - return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()) - }) + return aFav ? -1 : 1; + return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()); + }); } - return sorted.map(app => createResultEntry(app)) + return sorted.map(app => createResultEntry(app)); } // Use fuzzy search if available, fallback to simple search @@ -134,54 +134,54 @@ Item { "keys": ["name", "comment", "genericName", "executableName"], "threshold": -1000, "limit": 20 - }) + }); // Sort favorites first within fuzzy results while preserving fuzzysort order otherwise - const favoriteApps = Settings.data.appLauncher.favoriteApps || [] - const fav = [] - const nonFav = [] + const favoriteApps = Settings.data.appLauncher.favoriteApps || []; + const fav = []; + const nonFav = []; for (const r of fuzzyResults) { - const app = r.obj + const app = r.obj; if (favoriteApps.includes(getAppKey(app))) - fav.push(r) + fav.push(r); else - nonFav.push(r) + nonFav.push(r); } - return fav.concat(nonFav).map(result => createResultEntry(result.obj)) + return fav.concat(nonFav).map(result => createResultEntry(result.obj)); } else { // Fallback to simple search - const searchTerm = query.toLowerCase() + const searchTerm = query.toLowerCase(); return entries.filter(app => { - const name = (app.name || "").toLowerCase() - const comment = (app.comment || "").toLowerCase() - const generic = (app.genericName || "").toLowerCase() - const executable = getExecutableName(app).toLowerCase() - return name.includes(searchTerm) || comment.includes(searchTerm) || generic.includes(searchTerm) || executable.includes(searchTerm) + const name = (app.name || "").toLowerCase(); + const comment = (app.comment || "").toLowerCase(); + const generic = (app.genericName || "").toLowerCase(); + const executable = getExecutableName(app).toLowerCase(); + return name.includes(searchTerm) || comment.includes(searchTerm) || generic.includes(searchTerm) || executable.includes(searchTerm); }).sort((a, b) => { // Prioritize name matches, then executable matches - const aName = a.name.toLowerCase() - const bName = b.name.toLowerCase() - const aExecutable = getExecutableName(a).toLowerCase() - const bExecutable = getExecutableName(b).toLowerCase() - const aStarts = aName.startsWith(searchTerm) - const bStarts = bName.startsWith(searchTerm) - const aExecStarts = aExecutable.startsWith(searchTerm) - const bExecStarts = bExecutable.startsWith(searchTerm) + const aName = a.name.toLowerCase(); + const bName = b.name.toLowerCase(); + const aExecutable = getExecutableName(a).toLowerCase(); + const bExecutable = getExecutableName(b).toLowerCase(); + const aStarts = aName.startsWith(searchTerm); + const bStarts = bName.startsWith(searchTerm); + const aExecStarts = aExecutable.startsWith(searchTerm); + const bExecStarts = bExecutable.startsWith(searchTerm); // Prioritize name matches first if (aStarts && !bStarts) - return -1 + return -1; if (!aStarts && bStarts) - return 1 + return 1; // Then prioritize executable matches if (aExecStarts && !bExecStarts) - return -1 + return -1; if (!aExecStarts && bExecStarts) - return 1 + return 1; - return aName.localeCompare(bName) - }).slice(0, 20).map(app => createResultEntry(app)) + return aName.localeCompare(bName); + }).slice(0, 20).map(app => createResultEntry(app)); } } @@ -195,75 +195,75 @@ Item { "onActivate": function () { // Close the launcher/SmartPanel immediately without any animations. // Ensures we are not preventing the future focusing of the app - launcher.close() + launcher.close(); - Logger.d("ApplicationsPlugin", `Launching: ${app.name}`) + Logger.d("ApplicationsPlugin", `Launching: ${app.name}`); // Record usage and persist asynchronously if (Settings.data.appLauncher.sortByMostUsed) - recordUsage(app) + recordUsage(app); if (Settings.data.appLauncher.customLaunchPrefixEnabled && Settings.data.appLauncher.customLaunchPrefix) { // Use custom launch prefix - const prefix = Settings.data.appLauncher.customLaunchPrefix.split(" ") + const prefix = Settings.data.appLauncher.customLaunchPrefix.split(" "); if (app.runInTerminal) { - const terminal = Settings.data.appLauncher.terminalCommand.split(" ") - const command = prefix.concat(terminal.concat(app.command)) - Quickshell.execDetached(command) + const terminal = Settings.data.appLauncher.terminalCommand.split(" "); + const command = prefix.concat(terminal.concat(app.command)); + Quickshell.execDetached(command); } else { - const command = prefix.concat(app.command) - Quickshell.execDetached(command) + const command = prefix.concat(app.command); + Quickshell.execDetached(command); } } else if (Settings.data.appLauncher.useApp2Unit && app.id) { - Logger.d("ApplicationsPlugin", `Using app2unit for: ${app.id}`) + Logger.d("ApplicationsPlugin", `Using app2unit for: ${app.id}`); if (app.runInTerminal) - Quickshell.execDetached(["app2unit", "--", app.id + ".desktop"]) + Quickshell.execDetached(["app2unit", "--", app.id + ".desktop"]); else - Quickshell.execDetached(["app2unit", "--"].concat(app.command)) + Quickshell.execDetached(["app2unit", "--"].concat(app.command)); } else { // Fallback logic when app2unit is not used if (app.runInTerminal) { // If app.execute() fails for terminal apps, we handle it manually. - Logger.d("ApplicationsPlugin", "Executing terminal app manually: " + app.name) - const terminal = Settings.data.appLauncher.terminalCommand.split(" ") - const command = terminal.concat(app.command) - Quickshell.execDetached(command) + Logger.d("ApplicationsPlugin", "Executing terminal app manually: " + app.name); + const terminal = Settings.data.appLauncher.terminalCommand.split(" "); + const command = terminal.concat(app.command); + Quickshell.execDetached(command); } else if (app.execute) { // Default execution for GUI apps - app.execute() + app.execute(); } else { - Logger.w("ApplicationsPlugin", `Could not launch: ${app.name}. No valid launch method.`) + Logger.w("ApplicationsPlugin", `Could not launch: ${app.name}. No valid launch method.`); } } } - } + }; } // ------------------------- // Usage tracking helpers function getAppKey(app) { if (app && app.id) - return String(app.id) + return String(app.id); if (app && app.command && app.command.join) - return app.command.join(" ") - return String(app && app.name ? app.name : "unknown") + return app.command.join(" "); + return String(app && app.name ? app.name : "unknown"); } function getUsageCount(app) { - const key = getAppKey(app) - const m = usageAdapter && usageAdapter.counts ? usageAdapter.counts : null + const key = getAppKey(app); + const m = usageAdapter && usageAdapter.counts ? usageAdapter.counts : null; if (!m) - return 0 - const v = m[key] - return typeof v === 'number' && isFinite(v) ? v : 0 + return 0; + const v = m[key]; + return typeof v === 'number' && isFinite(v) ? v : 0; } function recordUsage(app) { - const key = getAppKey(app) + const key = getAppKey(app); if (!usageAdapter.counts) - usageAdapter.counts = ({}) - const current = getUsageCount(app) - usageAdapter.counts[key] = current + 1 + usageAdapter.counts = ({}); + const current = getUsageCount(app); + usageAdapter.counts[key] = current + 1; // Trigger save via debounced timer - saveTimer.restart() + saveTimer.restart(); } } diff --git a/Modules/Panels/Launcher/Plugins/CalculatorPlugin.qml b/Modules/Panels/Launcher/Plugins/CalculatorPlugin.qml index e8aaf5e3..bee3335b 100644 --- a/Modules/Panels/Launcher/Plugins/CalculatorPlugin.qml +++ b/Modules/Panels/Launcher/Plugins/CalculatorPlugin.qml @@ -1,6 +1,6 @@ import QtQuick -import qs.Commons import "../../../../Helpers/AdvancedMath.js" as AdvancedMath +import qs.Commons Item { property var launcher: null @@ -8,98 +8,106 @@ Item { function handleCommand(query) { // Handle >calc command or direct math expressions after > - return query.startsWith(">calc") || (query.startsWith(">") && query.length > 1 && isMathExpression(query.substring(1))) + return query.startsWith(">calc") || (query.startsWith(">") && query.length > 1 && isMathExpression(query.substring(1))); } function commands() { - return [{ - "name": ">calc", - "description": I18n.tr("plugins.calculator-description"), - "icon": "accessories-calculator", - "isImage": false, - "onActivate": function () { - launcher.setSearchText(">calc ") - } - }] + return [ + { + "name": ">calc", + "description": I18n.tr("plugins.calculator-description"), + "icon": "accessories-calculator", + "isImage": false, + "onActivate": function () { + launcher.setSearchText(">calc "); + } + } + ]; } function getResults(query) { - let expression = "" + let expression = ""; if (query.startsWith(">calc")) { - expression = query.substring(5).trim() + expression = query.substring(5).trim(); } else if (query.startsWith(">")) { - expression = query.substring(1).trim() + expression = query.substring(1).trim(); } else { - return [] + return []; } if (!expression) { - return [{ - "name": I18n.tr("plugins.calculator-name"), - "description": I18n.tr("plugins.calculator-enter-expression"), - "icon": "accessories-calculator", - "isImage": false, - "onActivate": function () {} - }] + return [ + { + "name": I18n.tr("plugins.calculator-name"), + "description": I18n.tr("plugins.calculator-enter-expression"), + "icon": "accessories-calculator", + "isImage": false, + "onActivate": function () {} + } + ]; } try { - let result = AdvancedMath.evaluate(expression.trim()) + let result = AdvancedMath.evaluate(expression.trim()); - return [{ - "name": AdvancedMath.formatResult(result), - "description": `${expression} = ${result}`, - "icon": "accessories-calculator", - "isImage": false, - "onActivate": function () { - // TODO: copy entry to clipboard via ClipHist - launcher.close() - } - }] + return [ + { + "name": AdvancedMath.formatResult(result), + "description": `${expression} = ${result}`, + "icon": "accessories-calculator", + "isImage": false, + "onActivate": function () { + // TODO: copy entry to clipboard via ClipHist + launcher.close(); + } + } + ]; } catch (error) { - return [{ - "name": I18n.tr("plugins.calculator-error"), - "description": error.message || "Invalid expression", - "icon": "dialog-error", - "isImage": false, - "onActivate": function () {} - }] + return [ + { + "name": I18n.tr("plugins.calculator-error"), + "description": error.message || "Invalid expression", + "icon": "dialog-error", + "isImage": false, + "onActivate": function () {} + } + ]; } } function evaluateExpression(expr) { // Sanitize input - only allow safe characters - const sanitized = expr.replace(/[^0-9\+\-\*\/\(\)\.\s\%]/g, '') + const sanitized = expr.replace(/[^0-9\+\-\*\/\(\)\.\s\%]/g, ''); if (sanitized !== expr) { - throw new Error("Invalid characters in expression") + throw new Error("Invalid characters in expression"); } // Don't allow empty expressions if (!sanitized.trim()) { - throw new Error("Empty expression") + throw new Error("Empty expression"); } try { // Use Function constructor for safe evaluation // This is safer than eval() but still evaluate math - const result = Function('"use strict"; return (' + sanitized + ')')() + const result = Function('"use strict"; return (' + sanitized + ')')(); // Check for valid result if (!isFinite(result)) { - throw new Error("Result is not a finite number") + throw new Error("Result is not a finite number"); } // Round to reasonable precision to avoid floating point issues - return Math.round(result * 1000000000) / 1000000000 + return Math.round(result * 1000000000) / 1000000000; } catch (e) { - throw new Error("Invalid mathematical expression") + throw new Error("Invalid mathematical expression"); } } function isMathExpression(expr) { // Check if string looks like a math expression // Allow digits, operators, parentheses, decimal points, and whitespace - return /^[\d\s\+\-\*\/\(\)\.\%]+$/.test(expr) - } + return /^[\d\s\+\-\*\/\(\)\.\%]+$/.test(expr); } +} diff --git a/Modules/Panels/Launcher/Plugins/ClipboardPlugin.qml b/Modules/Panels/Launcher/Plugins/ClipboardPlugin.qml index e6922b87..cb2d7b31 100644 --- a/Modules/Panels/Launcher/Plugins/ClipboardPlugin.qml +++ b/Modules/Panels/Launcher/Plugins/ClipboardPlugin.qml @@ -25,14 +25,14 @@ Item { if (gotResults && (lastSearchText === searchText)) { // Do not update results after the first fetch. // This will avoid the list resetting every 2seconds when the service updates. - return + return; } // Refresh results if we're waiting for data or if clipboard plugin is active if (isWaitingForData || (launcher && launcher.searchText.startsWith(">clip"))) { - isWaitingForData = false - gotResults = true + isWaitingForData = false; + gotResults = true; if (launcher) { - launcher.updateResults() + launcher.updateResults(); } } } @@ -40,142 +40,153 @@ Item { // Initialize plugin function init() { - Logger.i("ClipboardPlugin", "Initialized") + Logger.i("ClipboardPlugin", "Initialized"); // Pre-load clipboard data if service is active if (ClipboardService.active) { - ClipboardService.list(100) + ClipboardService.list(100); } } // Called when launcher opens function onOpened() { - isWaitingForData = true - gotResults = false - lastSearchText = "" + isWaitingForData = true; + gotResults = false; + lastSearchText = ""; // Refresh clipboard history when launcher opens if (ClipboardService.active) { - ClipboardService.list(100) + ClipboardService.list(100); } } // Check if this plugin handles the command function handleCommand(searchText) { - return searchText.startsWith(">clip") + return searchText.startsWith(">clip"); } // Return available commands when user types ">" function commands() { - return [{ - "name": ">clip", - "description": I18n.tr("plugins.clipboard-search-description"), - "icon": "text-x-generic", - "isImage": false, - "onActivate": function () { - launcher.setSearchText(">clip ") - } - }, { - "name": ">clip clear", - "description": I18n.tr("plugins.clipboard-clear-description"), - "icon": "text-x-generic", - "isImage": false, - "onActivate": function () { - ClipboardService.wipeAll() - launcher.close() - } - }] + return [ + { + "name": ">clip", + "description": I18n.tr("plugins.clipboard-search-description"), + "icon": "text-x-generic", + "isImage": false, + "onActivate": function () { + launcher.setSearchText(">clip "); + } + }, + { + "name": ">clip clear", + "description": I18n.tr("plugins.clipboard-clear-description"), + "icon": "text-x-generic", + "isImage": false, + "onActivate": function () { + ClipboardService.wipeAll(); + launcher.close(); + } + } + ]; } // Get search results function getResults(searchText) { if (!searchText.startsWith(">clip")) { - return [] + return []; } - lastSearchText = searchText - const results = [] - const query = searchText.slice(5).trim() + lastSearchText = searchText; + const results = []; + const query = searchText.slice(5).trim(); // Check if clipboard service is not active if (!ClipboardService.active) { - return [{ - "name": I18n.tr("plugins.clipboard-history-disabled"), - "description": I18n.tr("plugins.clipboard-history-disabled-description"), - "icon": "view-refresh", - "isImage": false, - "onActivate": function () {} - }] + return [ + { + "name": I18n.tr("plugins.clipboard-history-disabled"), + "description": I18n.tr("plugins.clipboard-history-disabled-description"), + "icon": "view-refresh", + "isImage": false, + "onActivate": function () {} + } + ]; } // Special command: clear if (query === "clear") { - return [{ - "name": I18n.tr("plugins.clipboard-clear-history"), - "description": I18n.tr("plugins.clipboard-clear-description-full"), - "icon": "delete_sweep", - "isImage": false, - "onActivate": function () { - ClipboardService.wipeAll() - launcher.close() - } - }] + return [ + { + "name": I18n.tr("plugins.clipboard-clear-history"), + "description": I18n.tr("plugins.clipboard-clear-description-full"), + "icon": "delete_sweep", + "isImage": false, + "onActivate": function () { + ClipboardService.wipeAll(); + launcher.close(); + } + } + ]; } // Show loading state if data is being loaded if (ClipboardService.loading || isWaitingForData) { - return [{ - "name": I18n.tr("plugins.clipboard-loading"), - "description": I18n.tr("plugins.clipboard-loading-description"), - "icon": "view-refresh", - "isImage": false, - "onActivate": function () {} - }] + return [ + { + "name": I18n.tr("plugins.clipboard-loading"), + "description": I18n.tr("plugins.clipboard-loading-description"), + "icon": "view-refresh", + "isImage": false, + "onActivate": function () {} + } + ]; } // Get clipboard items - const items = ClipboardService.items || [] + const items = ClipboardService.items || []; // If no items and we haven't tried loading yet, trigger a load if (items.count === 0 && !ClipboardService.loading) { - isWaitingForData = true - ClipboardService.list(100) - return [{ - "name": I18n.tr("plugins.clipboard-loading"), - "description": I18n.tr("plugins.clipboard-loading-description"), - "icon": "view-refresh", - "isImage": false, - "onActivate": function () {} - }] + isWaitingForData = true; + ClipboardService.list(100); + return [ + { + "name": I18n.tr("plugins.clipboard-loading"), + "description": I18n.tr("plugins.clipboard-loading-description"), + "icon": "view-refresh", + "isImage": false, + "onActivate": function () {} + } + ]; } // Search clipboard items - const searchTerm = query.toLowerCase() + const searchTerm = query.toLowerCase(); // Filter and format results items.forEach(function (item) { - const preview = (item.preview || "").toLowerCase() + const preview = (item.preview || "").toLowerCase(); // Skip if search term doesn't match if (searchTerm && preview.indexOf(searchTerm) === -1) { - return + return; } // Format the result based on type - let entry + let entry; if (item.isImage) { - entry = formatImageEntry(item) + entry = formatImageEntry(item); } else { - entry = formatTextEntry(item) + entry = formatTextEntry(item); } // Add activation handler entry.onActivate = function () { - ClipboardService.copyToClipboard(item.id) - launcher.close() - } + ClipboardService.copyToClipboard(item.id); + launcher.close(); + }; - results.push(entry) - }) + results.push(entry); + }); // Show empty state if no results if (results.length === 0) { @@ -186,16 +197,16 @@ Item { "isImage": false, "onActivate": function () {// Do nothing } - }) + }); } //Logger.i("ClipboardPlugin", `Returning ${results.length} results for query: "${query}"`) - return results + return results; } // Helper: Format image clipboard entry function formatImageEntry(item) { - const meta = parseImageMeta(item.preview) + const meta = parseImageMeta(item.preview); // The launcher's delegate will now be responsible for fetching the image data. // This function's role is to provide the necessary metadata for that request. @@ -208,31 +219,31 @@ Item { "imageHeight": meta ? meta.h : 0, "clipboardId": item.id, "mime": item.mime - } + }; } // Helper: Format text clipboard entry with preview function formatTextEntry(item) { - const preview = (item.preview || "").trim() - const lines = preview.split('\n').filter(l => l.trim()) + const preview = (item.preview || "").trim(); + const lines = preview.split('\n').filter(l => l.trim()); // Use first line as title, limit length - let title = lines[0] || "Empty text" + let title = lines[0] || "Empty text"; if (title.length > 60) { - title = title.substring(0, 57) + "..." + title = title.substring(0, 57) + "..."; } // Use second line or character count as description - let description = "" + let description = ""; if (lines.length > 1) { - description = lines[1] + description = lines[1]; if (description.length > 80) { - description = description.substring(0, 77) + "..." + description = description.substring(0, 77) + "..."; } } else { - const chars = preview.length - const words = preview.split(/\s+/).length - description = `${chars} characters, ${words} word${words !== 1 ? 's' : ''}` + const chars = preview.length; + const words = preview.split(/\s+/).length; + description = `${chars} characters, ${words} word${words !== 1 ? 's' : ''}`; } return { @@ -240,16 +251,16 @@ Item { "description": description, "icon": "text-x-generic", "isImage": false - } + }; } // Helper: Parse image metadata from preview string function parseImageMeta(preview) { - const re = /\[\[\s*binary data\s+([\d\.]+\s*(?:KiB|MiB|GiB|B))\s+(\w+)\s+(\d+)x(\d+)\s*\]\]/i - const match = (preview || "").match(re) + const re = /\[\[\s*binary data\s+([\d\.]+\s*(?:KiB|MiB|GiB|B))\s+(\w+)\s+(\d+)x(\d+)\s*\]\]/i; + const match = (preview || "").match(re); if (!match) { - return null + return null; } return { @@ -257,12 +268,12 @@ Item { "fmt": (match[2] || "").toUpperCase(), "w": Number(match[3]), "h": Number(match[4]) - } + }; } // Public method to get image data for a clipboard item // This can be called by the launcher when rendering function getImageForItem(clipboardId) { - return ClipboardService.getImageData ? ClipboardService.getImageData(clipboardId) : null + return ClipboardService.getImageData ? ClipboardService.getImageData(clipboardId) : null; } } diff --git a/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml b/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml index 05679b35..67ed3524 100644 --- a/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml +++ b/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml @@ -1,13 +1,13 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell -import Quickshell.Wayland import Quickshell.Services.Notifications +import Quickshell.Wayland import qs.Commons +import qs.Modules.MainScreen import qs.Services.System import qs.Widgets -import qs.Modules.MainScreen // Notification History panel SmartPanel { @@ -17,7 +17,7 @@ SmartPanel { preferredHeight: Math.round(540 * Style.uiScaleRatio) onOpened: function () { - NotificationService.updateLastSeenTs() + NotificationService.updateLastSeenTs(); } panelContent: Rectangle { @@ -67,9 +67,9 @@ SmartPanel { tooltipText: I18n.tr("tooltips.clear-history") baseSize: Style.baseWidgetSize * 0.8 onClicked: { - NotificationService.clearHistory() + NotificationService.clearHistory(); // Close panel as there is nothing more to see. - root.close() + root.close(); } } @@ -177,9 +177,9 @@ SmartPanel { cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor onClicked: { if (scrollView.expandedId === notificationId) { - scrollView.expandedId = "" + scrollView.expandedId = ""; } else { - scrollView.expandedId = notificationId + scrollView.expandedId = notificationId; } } } @@ -227,11 +227,11 @@ SmartPanel { visible: model.urgency !== 1 color: { if (model.urgency === 2) - return Color.mError + return Color.mError; else if (model.urgency === 0) - return Color.mOnSurfaceVariant + return Color.mOnSurfaceVariant; else - return Color.transparent + return Color.transparent; } } @@ -312,7 +312,7 @@ SmartPanel { anchors.verticalCenter: parent.verticalCenter onClicked: { - NotificationService.removeFromHistory(notificationId) + NotificationService.removeFromHistory(notificationId); } } } diff --git a/Modules/Panels/SessionMenu/SessionMenu.qml b/Modules/Panels/SessionMenu/SessionMenu.qml index e4aaece1..4b5f9cbd 100644 --- a/Modules/Panels/SessionMenu/SessionMenu.qml +++ b/Modules/Panels/SessionMenu/SessionMenu.qml @@ -4,31 +4,31 @@ import QtQuick.Effects import QtQuick.Layouts import Quickshell import Quickshell.Io -import Quickshell.Widgets import Quickshell.Wayland +import Quickshell.Widgets import qs.Commons +import qs.Modules.MainScreen import qs.Services.Compositor import qs.Services.UI import qs.Widgets -import qs.Modules.MainScreen SmartPanel { id: root preferredWidth: Math.round(400 * Style.uiScaleRatio) preferredHeight: { - var headerHeight = Settings.data.sessionMenu.showHeader ? Style.baseWidgetSize * 0.6 : 0 + var headerHeight = Settings.data.sessionMenu.showHeader ? Style.baseWidgetSize * 0.6 : 0; - var dividerHeight = Settings.data.sessionMenu.showHeader ? Style.marginS : 0 - var buttonHeight = Style.baseWidgetSize * 1.3 * Style.uiScaleRatio - var buttonSpacing = Style.marginS - var enabledCount = powerOptions.length + var dividerHeight = Settings.data.sessionMenu.showHeader ? Style.marginS : 0; + var buttonHeight = Style.baseWidgetSize * 1.3 * Style.uiScaleRatio; + var buttonSpacing = Style.marginS; + var enabledCount = powerOptions.length; - var headerSpacing = Settings.data.sessionMenu.showHeader ? (Style.marginL * 2) : 0 - var baseHeight = (Style.marginL * 4) + headerHeight + dividerHeight + headerSpacing - var buttonsHeight = enabledCount > 0 ? (buttonHeight * enabledCount) + (buttonSpacing * (enabledCount - 1)) : 0 + var headerSpacing = Settings.data.sessionMenu.showHeader ? (Style.marginL * 2) : 0; + var baseHeight = (Style.marginL * 4) + headerHeight + dividerHeight + headerSpacing; + var buttonsHeight = enabledCount > 0 ? (buttonHeight * enabledCount) + (buttonSpacing * (enabledCount - 1)) : 0; - return Math.round(baseHeight + buttonsHeight) + return Math.round(baseHeight + buttonsHeight); } // Positioning @@ -89,216 +89,216 @@ SmartPanel { // Build powerOptions from settings, filtering enabled ones and adding metadata property var powerOptions: { - var options = [] - var settingsOptions = Settings.data.sessionMenu.powerOptions || [] + var options = []; + var settingsOptions = Settings.data.sessionMenu.powerOptions || []; for (var i = 0; i < settingsOptions.length; i++) { - var settingOption = settingsOptions[i] + var settingOption = settingsOptions[i]; if (settingOption.enabled && actionMetadata[settingOption.action]) { - var metadata = actionMetadata[settingOption.action] + var metadata = actionMetadata[settingOption.action]; options.push({ "action": settingOption.action, "icon": metadata.icon, "title": metadata.title, "isShutdown": metadata.isShutdown, "countdownEnabled": settingOption.countdownEnabled !== undefined ? settingOption.countdownEnabled : true - }) + }); } } - return options + return options; } // Update powerOptions when settings change Connections { target: Settings.data.sessionMenu function onPowerOptionsChanged() { - var options = [] - var settingsOptions = Settings.data.sessionMenu.powerOptions || [] + var options = []; + var settingsOptions = Settings.data.sessionMenu.powerOptions || []; for (var i = 0; i < settingsOptions.length; i++) { - var settingOption = settingsOptions[i] + var settingOption = settingsOptions[i]; if (settingOption.enabled && actionMetadata[settingOption.action]) { - var metadata = actionMetadata[settingOption.action] + var metadata = actionMetadata[settingOption.action]; options.push({ "action": settingOption.action, "icon": metadata.icon, "title": metadata.title, "isShutdown": metadata.isShutdown, "countdownEnabled": settingOption.countdownEnabled !== undefined ? settingOption.countdownEnabled : true - }) + }); } } - root.powerOptions = options + root.powerOptions = options; } } // Lifecycle handlers onOpened: { - selectedIndex = 0 + selectedIndex = 0; } onClosed: { - cancelTimer() - selectedIndex = 0 + cancelTimer(); + selectedIndex = 0; } // Timer management function startTimer(action) { // Check if global countdown is disabled if (!Settings.data.sessionMenu.enableCountdown) { - executeAction(action) - return + executeAction(action); + return; } // Check per-item countdown setting - var option = null + var option = null; for (var i = 0; i < powerOptions.length; i++) { if (powerOptions[i].action === action) { - option = powerOptions[i] - break + option = powerOptions[i]; + break; } } // If this specific action has countdown disabled, execute immediately if (option && option.countdownEnabled === false) { - executeAction(action) - return + executeAction(action); + return; } if (timerActive && pendingAction === action) { // Second click - execute immediately - executeAction(action) - return + executeAction(action); + return; } - pendingAction = action - timeRemaining = timerDuration - timerActive = true - countdownTimer.start() + pendingAction = action; + timeRemaining = timerDuration; + timerActive = true; + countdownTimer.start(); } function cancelTimer() { - timerActive = false - pendingAction = "" - timeRemaining = 0 - countdownTimer.stop() + timerActive = false; + pendingAction = ""; + timeRemaining = 0; + countdownTimer.stop(); } function executeAction(action) { // Stop timer but don't reset other properties yet - countdownTimer.stop() + countdownTimer.stop(); switch (action) { case "lock": // Access lockScreen via PanelService if (PanelService.lockScreen && !PanelService.lockScreen.active) { - PanelService.lockScreen.active = true + PanelService.lockScreen.active = true; } - break + break; case "suspend": // Check if we should lock before suspending if (Settings.data.general.lockOnSuspend) { - CompositorService.lockAndSuspend() + CompositorService.lockAndSuspend(); } else { - CompositorService.suspend() + CompositorService.suspend(); } - break + break; case "hibernate": - CompositorService.hibernate() - break + CompositorService.hibernate(); + break; case "reboot": - CompositorService.reboot() - break + CompositorService.reboot(); + break; case "logout": - CompositorService.logout() - break + CompositorService.logout(); + break; case "shutdown": - CompositorService.shutdown() - break + CompositorService.shutdown(); + break; } // Reset timer state and close panel - cancelTimer() - root.close() + cancelTimer(); + root.close(); } // Navigation functions function selectNextWrapped() { if (powerOptions.length > 0) { - selectedIndex = (selectedIndex + 1) % powerOptions.length + selectedIndex = (selectedIndex + 1) % powerOptions.length; } } function selectPreviousWrapped() { if (powerOptions.length > 0) { - selectedIndex = (((selectedIndex - 1) % powerOptions.length) + powerOptions.length) % powerOptions.length + selectedIndex = (((selectedIndex - 1) % powerOptions.length) + powerOptions.length) % powerOptions.length; } } function selectFirst() { - selectedIndex = 0 + selectedIndex = 0; } function selectLast() { if (powerOptions.length > 0) { - selectedIndex = powerOptions.length - 1 + selectedIndex = powerOptions.length - 1; } else { - selectedIndex = 0 + selectedIndex = 0; } } function activate() { if (powerOptions.length > 0 && powerOptions[selectedIndex]) { - const option = powerOptions[selectedIndex] - startTimer(option.action) + const option = powerOptions[selectedIndex]; + startTimer(option.action); } } // Override keyboard handlers from SmartPanel function onEscapePressed() { if (timerActive) { - cancelTimer() + cancelTimer(); } else { - root.close() + root.close(); } } function onTabPressed() { - selectNextWrapped() + selectNextWrapped(); } function onBackTabPressed() { - selectPreviousWrapped() + selectPreviousWrapped(); } function onUpPressed() { - selectPreviousWrapped() + selectPreviousWrapped(); } function onDownPressed() { - selectNextWrapped() + selectNextWrapped(); } function onReturnPressed() { - activate() + activate(); } function onHomePressed() { - selectFirst() + selectFirst(); } function onEndPressed() { - selectLast() + selectLast(); } function onCtrlJPressed() { - selectNextWrapped() + selectNextWrapped(); } function onCtrlKPressed() { - selectPreviousWrapped() + selectPreviousWrapped(); } // Countdown timer @@ -307,9 +307,9 @@ SmartPanel { interval: 100 repeat: true onTriggered: { - timeRemaining -= interval + timeRemaining -= interval; if (timeRemaining <= 0) { - executeAction(pendingAction) + executeAction(pendingAction); } } } @@ -320,23 +320,23 @@ SmartPanel { // Navigation functions function selectFirst() { - root.selectFirst() + root.selectFirst(); } function selectLast() { - root.selectLast() + root.selectLast(); } function selectNextWrapped() { - root.selectNextWrapped() + root.selectNextWrapped(); } function selectPreviousWrapped() { - root.selectPreviousWrapped() + root.selectPreviousWrapped(); } function activate() { - root.activate() + root.activate(); } NBox { @@ -379,10 +379,10 @@ SmartPanel { colorFg: timerActive ? Color.mError : Color.mOnSurface onClicked: { if (timerActive) { - cancelTimer() + cancelTimer(); } else { - cancelTimer() - root.close() + cancelTimer(); + root.close(); } } } @@ -407,8 +407,8 @@ SmartPanel { isShutdown: modelData.isShutdown || false isSelected: index === selectedIndex onClicked: { - selectedIndex = index - startTimer(modelData.action) + selectedIndex = index; + startTimer(modelData.action); } pending: timerActive && pendingAction === modelData.action } @@ -434,12 +434,12 @@ SmartPanel { radius: Style.radiusS color: { if (pending) { - return Qt.alpha(Color.mPrimary, 0.08) + return Qt.alpha(Color.mPrimary, 0.08); } if (isSelected || mouseArea.containsMouse) { - return Color.mHover + return Color.mHover; } - return Color.transparent + return Color.transparent; } border.width: pending ? Math.max(Style.borderM) : 0 @@ -464,12 +464,12 @@ SmartPanel { icon: buttonRoot.icon color: { if (buttonRoot.pending) - return Color.mPrimary + return Color.mPrimary; if (buttonRoot.isShutdown && !buttonRoot.isSelected && !mouseArea.containsMouse) - return Color.mError + return Color.mError; if (buttonRoot.isSelected || mouseArea.containsMouse) - return Color.mOnHover - return Color.mOnSurface + return Color.mOnHover; + return Color.mOnSurface; } pointSize: Style.fontSizeXXL width: Style.baseWidgetSize * 0.5 @@ -499,12 +499,12 @@ SmartPanel { pointSize: Style.fontSizeM color: { if (buttonRoot.pending) - return Color.mPrimary + return Color.mPrimary; if (buttonRoot.isShutdown && !buttonRoot.isSelected && !mouseArea.containsMouse) - return Color.mError + return Color.mError; if (buttonRoot.isSelected || mouseArea.containsMouse) - return Color.mOnHover - return Color.mOnSurface + return Color.mOnHover; + return Color.mOnSurface; } Behavior on color { diff --git a/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml index 6a3d8958..44ced470 100644 --- a/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml @@ -3,8 +3,8 @@ import QtQuick.Controls import QtQuick.Effects import QtQuick.Layouts import qs.Commons -import qs.Widgets import qs.Services.UI +import qs.Widgets // Widget Settings Dialog Component Popup { @@ -27,7 +27,7 @@ Popup { onOpened: { // Load settings when popup opens with data if (widgetData && widgetId) { - loadWidgetSettings() + loadWidgetSettings(); } } @@ -102,9 +102,9 @@ Popup { icon: "check" onClicked: { if (settingsLoader.item && settingsLoader.item.saveSettings) { - var newSettings = settingsLoader.item.saveSettings() - root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings) - root.close() + var newSettings = settingsLoader.item.saveSettings(); + root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings); + root.close(); } } } @@ -112,13 +112,13 @@ Popup { } function loadWidgetSettings() { - const source = BarWidgetRegistry.widgetSettingsMap[widgetId] + const source = BarWidgetRegistry.widgetSettingsMap[widgetId]; if (source) { // Use setSource to pass properties at creation time settingsLoader.setSource(source, { "widgetData": widgetData, "widgetMetadata": BarWidgetRegistry.widgetMetadata[widgetId] - }) + }); } } } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml index 140fc511..2b74b5fe 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml @@ -22,35 +22,39 @@ ColumnLayout { Component.onCompleted: { if (widgetData && widgetData.hideMode !== undefined) { - valueHideMode = widgetData.hideMode + valueHideMode = widgetData.hideMode; } } function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.hideMode = valueHideMode - settings.showIcon = valueShowIcon - settings.scrollingMode = valueScrollingMode - settings.maxWidth = parseInt(widthInput.text) || widgetMetadata.maxWidth - settings.useFixedWidth = valueUseFixedWidth - settings.colorizeIcons = valueColorizeIcons - return settings + var settings = Object.assign({}, widgetData || {}); + settings.hideMode = valueHideMode; + settings.showIcon = valueShowIcon; + settings.scrollingMode = valueScrollingMode; + settings.maxWidth = parseInt(widthInput.text) || widgetMetadata.maxWidth; + settings.useFixedWidth = valueUseFixedWidth; + settings.colorizeIcons = valueColorizeIcons; + return settings; } NComboBox { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.active-window.hide-mode.label") description: I18n.tr("bar.widget-settings.active-window.hide-mode.description") - model: [{ + model: [ + { "key": "visible", "name": I18n.tr("options.hide-modes.visible") - }, { + }, + { "key": "hidden", "name": I18n.tr("options.hide-modes.hidden") - }, { + }, + { "key": "transparent", "name": I18n.tr("options.hide-modes.transparent") - }] + } + ] currentKey: root.valueHideMode onSelected: key => root.valueHideMode = key } @@ -91,16 +95,20 @@ ColumnLayout { NComboBox { label: I18n.tr("bar.widget-settings.active-window.scrolling-mode.label") description: I18n.tr("bar.widget-settings.active-window.scrolling-mode.description") - model: [{ + model: [ + { "key": "always", "name": I18n.tr("options.scrolling-modes.always") - }, { + }, + { "key": "hover", "name": I18n.tr("options.scrolling-modes.hover") - }, { + }, + { "key": "never", "name": I18n.tr("options.scrolling-modes.never") - }] + } + ] currentKey: valueScrollingMode onSelected: key => valueScrollingMode = key minimumWidth: 200 diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/AudioVisualizerSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/AudioVisualizerSettings.qml index dea5809d..754cc62c 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/AudioVisualizerSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/AudioVisualizerSettings.qml @@ -17,11 +17,11 @@ ColumnLayout { property string valueColorName: widgetData.colorName !== undefined ? widgetData.colorName : widgetMetadata.colorName function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.width = parseInt(widthInput.text) || widgetMetadata.width - settings.hideWhenIdle = valueHideWhenIdle - settings.colorName = valueColorName - return settings + var settings = Object.assign({}, widgetData || {}); + settings.width = parseInt(widthInput.text) || widgetMetadata.width; + settings.hideWhenIdle = valueHideWhenIdle; + settings.colorName = valueColorName; + return settings; } NTextInput { @@ -37,22 +37,28 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.audio-visualizer.color-name.label") description: I18n.tr("bar.widget-settings.audio-visualizer.color-name.description") - model: [{ + model: [ + { "key": "primary", "name": I18n.tr("options.colors.primary") - }, { + }, + { "key": "secondary", "name": I18n.tr("options.colors.secondary") - }, { + }, + { "key": "tertiary", "name": I18n.tr("options.colors.tertiary") - }, { + }, + { "key": "onSurface", "name": I18n.tr("options.colors.onSurface") - }, { + }, + { "key": "error", "name": I18n.tr("options.colors.error") - }] + } + ] currentKey: root.valueColorName onSelected: key => root.valueColorName = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/BatterySettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/BatterySettings.qml index 7a5f046c..8b23d553 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/BatterySettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/BatterySettings.qml @@ -17,26 +17,30 @@ ColumnLayout { property int valueWarningThreshold: widgetData.warningThreshold !== undefined ? widgetData.warningThreshold : widgetMetadata.warningThreshold function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.displayMode = valueDisplayMode - settings.warningThreshold = valueWarningThreshold - return settings + var settings = Object.assign({}, widgetData || {}); + settings.displayMode = valueDisplayMode; + settings.warningThreshold = valueWarningThreshold; + return settings; } NComboBox { label: I18n.tr("bar.widget-settings.battery.display-mode.label") description: I18n.tr("bar.widget-settings.battery.display-mode.description") minimumWidth: 134 - model: [{ + model: [ + { "key": "onhover", "name": I18n.tr("options.display-mode.on-hover") - }, { + }, + { "key": "alwaysShow", "name": I18n.tr("options.display-mode.always-show") - }, { + }, + { "key": "alwaysHide", "name": I18n.tr("options.display-mode.always-hide") - }] + } + ] currentKey: root.valueDisplayMode onSelected: key => root.valueDisplayMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/BluetoothSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/BluetoothSettings.qml index d6548476..72353f4d 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/BluetoothSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/BluetoothSettings.qml @@ -15,25 +15,29 @@ ColumnLayout { property string valueDisplayMode: widgetData.displayMode !== undefined ? widgetData.displayMode : widgetMetadata.displayMode function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.displayMode = valueDisplayMode - return settings + var settings = Object.assign({}, widgetData || {}); + settings.displayMode = valueDisplayMode; + return settings; } NComboBox { label: I18n.tr("bar.widget-settings.battery.display-mode.label") description: I18n.tr("bar.widget-settings.battery.display-mode.description") minimumWidth: 134 - model: [{ + model: [ + { "key": "onhover", "name": I18n.tr("options.display-mode.on-hover") - }, { + }, + { "key": "alwaysShow", "name": I18n.tr("options.display-mode.always-show") - }, { + }, + { "key": "alwaysHide", "name": I18n.tr("options.display-mode.always-hide") - }] + } + ] currentKey: root.valueDisplayMode onSelected: key => root.valueDisplayMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/BrightnessSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/BrightnessSettings.qml index ecf4869c..8ebddbbd 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/BrightnessSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/BrightnessSettings.qml @@ -16,25 +16,29 @@ ColumnLayout { property string valueDisplayMode: widgetData.displayMode !== undefined ? widgetData.displayMode : widgetMetadata.displayMode function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.displayMode = valueDisplayMode - return settings + var settings = Object.assign({}, widgetData || {}); + settings.displayMode = valueDisplayMode; + return settings; } NComboBox { label: I18n.tr("bar.widget-settings.brightness.display-mode.label") description: I18n.tr("bar.widget-settings.brightness.display-mode.description") minimumWidth: 134 - model: [{ + model: [ + { "key": "onhover", "name": I18n.tr("options.display-mode.on-hover") - }, { + }, + { "key": "alwaysShow", "name": I18n.tr("options.display-mode.always-show") - }, { + }, + { "key": "alwaysHide", "name": I18n.tr("options.display-mode.always-hide") - }] + } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/ClockSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/ClockSettings.qml index 3e650121..b273e3e3 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/ClockSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/ClockSettings.qml @@ -2,8 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import qs.Commons -import qs.Widgets import qs.Services.System +import qs.Widgets ColumnLayout { id: root @@ -28,13 +28,13 @@ ColumnLayout { readonly property var now: Time.now function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.usePrimaryColor = valueUsePrimaryColor - settings.useCustomFont = valueUseCustomFont - settings.customFont = valueCustomFont - settings.formatHorizontal = valueFormatHorizontal.trim() - settings.formatVertical = valueFormatVertical.trim() - return settings + var settings = Object.assign({}, widgetData || {}); + settings.usePrimaryColor = valueUsePrimaryColor; + settings.useCustomFont = valueUseCustomFont; + settings.customFont = valueCustomFont; + settings.formatHorizontal = valueFormatHorizontal.trim(); + settings.formatVertical = valueFormatVertical.trim(); + return settings; } // Function to insert token at cursor position in the focused input @@ -42,25 +42,25 @@ ColumnLayout { if (!focusedInput || !focusedInput.inputItem) { // If no input is focused, default to horiz if (inputHoriz.inputItem) { - inputHoriz.inputItem.focus = true - focusedInput = inputHoriz + inputHoriz.inputItem.focus = true; + focusedInput = inputHoriz; } } if (focusedInput && focusedInput.inputItem) { - var input = focusedInput.inputItem - var cursorPos = input.cursorPosition - var currentText = input.text + var input = focusedInput.inputItem; + var cursorPos = input.cursorPosition; + var currentText = input.text; // Insert token at cursor position - var newText = currentText.substring(0, cursorPos) + token + currentText.substring(cursorPos) - input.text = newText + " " + var newText = currentText.substring(0, cursorPos) + token + currentText.substring(cursorPos); + input.text = newText + " "; // Move cursor after the inserted token - input.cursorPosition = cursorPos + token.length + 1 + input.cursorPosition = cursorPos + token.length + 1; // Ensure the input keeps focus - input.focus = true + input.focus = true; } } @@ -92,7 +92,7 @@ ColumnLayout { popupHeight: 420 minimumWidth: 300 onSelected: function (key) { - valueCustomFont = key + valueCustomFont = key; } } @@ -131,9 +131,9 @@ ColumnLayout { if (inputItem) { inputItem.onActiveFocusChanged.connect(function () { if (inputItem.activeFocus) { - root.focusedInput = inputHoriz + root.focusedInput = inputHoriz; } - }) + }); } } } @@ -155,9 +155,9 @@ ColumnLayout { if (inputItem) { inputItem.onActiveFocusChanged.connect(function () { if (inputItem.activeFocus) { - root.focusedInput = inputVert + root.focusedInput = inputVert; } - }) + }); } } } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml index 1b423d9c..7a0aa453 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml @@ -20,12 +20,12 @@ ColumnLayout { property bool valueColorizeDistroLogo: widgetData.colorizeDistroLogo !== undefined ? widgetData.colorizeDistroLogo : (widgetMetadata.colorizeDistroLogo !== undefined ? widgetMetadata.colorizeDistroLogo : false) function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.icon = valueIcon - settings.useDistroLogo = valueUseDistroLogo - settings.customIconPath = valueCustomIconPath - settings.colorizeDistroLogo = valueColorizeDistroLogo - return settings + var settings = Object.assign({}, widgetData || {}); + settings.icon = valueIcon; + settings.useDistroLogo = valueUseDistroLogo; + settings.customIconPath = valueCustomIconPath; + settings.colorizeDistroLogo = valueColorizeDistroLogo; + return settings; } NToggle { @@ -33,10 +33,10 @@ ColumnLayout { description: I18n.tr("bar.widget-settings.control-center.use-distro-logo.description") checked: valueUseDistroLogo onToggled: function (checked) { - valueUseDistroLogo = checked + valueUseDistroLogo = checked; if (checked) { - valueCustomIconPath = "" - valueIcon = "" + valueCustomIconPath = ""; + valueIcon = ""; } } } @@ -47,7 +47,7 @@ ColumnLayout { description: I18n.tr("bar.widget-settings.control-center.colorize-distro-logo.description") checked: valueColorizeDistroLogo onToggled: function (checked) { - valueColorizeDistroLogo = checked + valueColorizeDistroLogo = checked; } } @@ -94,8 +94,8 @@ ColumnLayout { id: iconPicker initialIcon: valueIcon onIconSelected: iconName => { - valueIcon = iconName - valueCustomIconPath = "" + valueIcon = iconName; + valueCustomIconPath = ""; } } @@ -107,7 +107,7 @@ ColumnLayout { initialPath: Quickshell.env("HOME") onAccepted: paths => { if (paths.length > 0) { - valueCustomIconPath = paths[0] // Use first selected file + valueCustomIconPath = paths[0]; // Use first selected file } } } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml index 208d4e11..a990638a 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml @@ -19,21 +19,21 @@ ColumnLayout { property bool valueHideTextInVerticalBar: widgetData.hideTextInVerticalBar !== undefined ? widgetData.hideTextInVerticalBar : widgetMetadata.hideTextInVerticalBar function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.icon = valueIcon - settings.leftClickExec = leftClickExecInput.text - settings.leftClickUpdateText = leftClickUpdateText.checked - settings.rightClickExec = rightClickExecInput.text - settings.rightClickUpdateText = rightClickUpdateText.checked - settings.middleClickExec = middleClickExecInput.text - settings.middleClickUpdateText = middleClickUpdateText.checked - settings.textCommand = textCommandInput.text - settings.textCollapse = textCollapseInput.text - settings.textStream = valueTextStream - settings.parseJson = valueParseJson - settings.hideTextInVerticalBar = valueHideTextInVerticalBar - settings.textIntervalMs = parseInt(textIntervalInput.text || textIntervalInput.placeholderText, 10) - return settings + var settings = Object.assign({}, widgetData || {}); + settings.icon = valueIcon; + settings.leftClickExec = leftClickExecInput.text; + settings.leftClickUpdateText = leftClickUpdateText.checked; + settings.rightClickExec = rightClickExecInput.text; + settings.rightClickUpdateText = rightClickUpdateText.checked; + settings.middleClickExec = middleClickExecInput.text; + settings.middleClickUpdateText = middleClickUpdateText.checked; + settings.textCommand = textCommandInput.text; + settings.textCollapse = textCollapseInput.text; + settings.textStream = valueTextStream; + settings.parseJson = valueParseJson; + settings.hideTextInVerticalBar = valueHideTextInVerticalBar; + settings.textIntervalMs = parseInt(textIntervalInput.text || textIntervalInput.placeholderText, 10); + return settings; } RowLayout { @@ -61,7 +61,7 @@ ColumnLayout { id: iconPicker initialIcon: valueIcon onIconSelected: function (iconName) { - valueIcon = iconName + valueIcon = iconName; } } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml index 5b2bc230..f39c1136 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml @@ -16,25 +16,29 @@ ColumnLayout { property string valueDisplayMode: widgetData.displayMode !== undefined ? widgetData.displayMode : widgetMetadata.displayMode function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.displayMode = valueDisplayMode - return settings + var settings = Object.assign({}, widgetData || {}); + settings.displayMode = valueDisplayMode; + return settings; } NComboBox { label: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.label") description: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.description") minimumWidth: 134 - model: [{ + model: [ + { "key": "onhover", "name": I18n.tr("options.display-mode.on-hover") - }, { + }, + { "key": "forceOpen", "name": I18n.tr("options.display-mode.force-open") - }, { + }, + { "key": "alwaysHide", "name": I18n.tr("options.display-mode.always-hide") - }] + } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/LockKeysSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/LockKeysSettings.qml index dd9b12ef..345c0039 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/LockKeysSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/LockKeysSettings.qml @@ -22,14 +22,14 @@ ColumnLayout { property string scrollIcon: widgetData.scrollLockIcon !== undefined ? widgetData.scrollLockIcon : widgetMetadata.scrollLockIcon function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.showCapsLock = valueShowCapsLock - settings.showNumLock = valueShowNumLock - settings.showScrollLock = valueShowScrollLock - settings.capsLockIcon = capsIcon - settings.numLockIcon = numIcon - settings.scrollLockIcon = scrollIcon - return settings + var settings = Object.assign({}, widgetData || {}); + settings.showCapsLock = valueShowCapsLock; + settings.showNumLock = valueShowNumLock; + settings.showScrollLock = valueShowScrollLock; + settings.capsLockIcon = capsIcon; + settings.numLockIcon = numIcon; + settings.scrollLockIcon = scrollIcon; + return settings; } RowLayout { @@ -61,7 +61,7 @@ ColumnLayout { initialIcon: capsIcon query: "letter-c" onIconSelected: function (iconName) { - capsIcon = iconName + capsIcon = iconName; } } @@ -94,7 +94,7 @@ ColumnLayout { initialIcon: numIcon query: "letter-n" onIconSelected: function (iconName) { - numIcon = iconName + numIcon = iconName; } } @@ -127,7 +127,7 @@ ColumnLayout { initialIcon: scrollIcon query: "letter-s" onIconSelected: function (iconName) { - scrollIcon = iconName + scrollIcon = iconName; } } } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/MediaMiniSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/MediaMiniSettings.qml index 808fe3dc..c8e3fa0f 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/MediaMiniSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/MediaMiniSettings.qml @@ -25,40 +25,45 @@ ColumnLayout { Component.onCompleted: { if (widgetData && widgetData.hideMode !== undefined) { - valueHideMode = widgetData.hideMode + valueHideMode = widgetData.hideMode; } } function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.hideMode = valueHideMode + var settings = Object.assign({}, widgetData || {}); + settings.hideMode = valueHideMode; // No longer store hideWhenIdle separately; kept for backward compatibility only - settings.showAlbumArt = valueShowAlbumArt - settings.showVisualizer = valueShowVisualizer - settings.visualizerType = valueVisualizerType - settings.scrollingMode = valueScrollingMode - settings.maxWidth = parseInt(widthInput.text) || widgetMetadata.maxWidth - settings.useFixedWidth = valueUseFixedWidth - return settings + settings.showAlbumArt = valueShowAlbumArt; + settings.showVisualizer = valueShowVisualizer; + settings.visualizerType = valueVisualizerType; + settings.scrollingMode = valueScrollingMode; + settings.maxWidth = parseInt(widthInput.text) || widgetMetadata.maxWidth; + settings.useFixedWidth = valueUseFixedWidth; + return settings; } NComboBox { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.media-mini.hide-mode.label") description: I18n.tr("bar.widget-settings.media-mini.hide-mode.description") - model: [{ + model: [ + { "key": "visible", "name": I18n.tr("options.hide-modes.visible") - }, { + }, + { "key": "hidden", "name": I18n.tr("options.hide-modes.hidden") - }, { + }, + { "key": "transparent", "name": I18n.tr("options.hide-modes.transparent") - }, { + }, + { "key": "idle", "name": I18n.tr("options.hide-modes.idle") - }] + } + ] currentKey: root.valueHideMode onSelected: key => root.valueHideMode = key } @@ -81,16 +86,20 @@ ColumnLayout { visible: valueShowVisualizer label: I18n.tr("bar.widget-settings.media-mini.visualizer-type.label") description: I18n.tr("bar.widget-settings.media-mini.visualizer-type.description") - model: [{ + model: [ + { "key": "linear", "name": I18n.tr("options.visualizer-types.linear") - }, { + }, + { "key": "mirrored", "name": I18n.tr("options.visualizer-types.mirrored") - }, { + }, + { "key": "wave", "name": I18n.tr("options.visualizer-types.wave") - }] + } + ] currentKey: valueVisualizerType onSelected: key => valueVisualizerType = key minimumWidth: 200 @@ -115,16 +124,20 @@ ColumnLayout { NComboBox { label: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.label") description: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.description") - model: [{ + model: [ + { "key": "always", "name": I18n.tr("options.scrolling-modes.always") - }, { + }, + { "key": "hover", "name": I18n.tr("options.scrolling-modes.hover") - }, { + }, + { "key": "never", "name": I18n.tr("options.scrolling-modes.never") - }] + } + ] currentKey: valueScrollingMode onSelected: key => valueScrollingMode = key minimumWidth: 200 diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/MicrophoneSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/MicrophoneSettings.qml index 3ff2ee58..674e4c09 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/MicrophoneSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/MicrophoneSettings.qml @@ -16,25 +16,29 @@ ColumnLayout { property string valueDisplayMode: widgetData.displayMode !== undefined ? widgetData.displayMode : widgetMetadata.displayMode function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.displayMode = valueDisplayMode - return settings + var settings = Object.assign({}, widgetData || {}); + settings.displayMode = valueDisplayMode; + return settings; } NComboBox { label: I18n.tr("bar.widget-settings.microphone.display-mode.label") description: I18n.tr("bar.widget-settings.microphone.display-mode.description") minimumWidth: 134 - model: [{ + model: [ + { "key": "onhover", "name": I18n.tr("options.display-mode.on-hover") - }, { + }, + { "key": "alwaysShow", "name": I18n.tr("options.display-mode.always-show") - }, { + }, + { "key": "alwaysHide", "name": I18n.tr("options.display-mode.always-hide") - }] + } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml index ba6475af..d06e5ca9 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml @@ -17,10 +17,10 @@ ColumnLayout { property bool valueHideWhenZero: widgetData.hideWhenZero !== undefined ? widgetData.hideWhenZero : widgetMetadata.hideWhenZero function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.showUnreadBadge = valueShowUnreadBadge - settings.hideWhenZero = valueHideWhenZero - return settings + var settings = Object.assign({}, widgetData || {}); + settings.showUnreadBadge = valueShowUnreadBadge; + settings.hideWhenZero = valueHideWhenZero; + return settings; } NToggle { diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/SessionMenuSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/SessionMenuSettings.qml index f4adf0be..71ec8327 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/SessionMenuSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/SessionMenuSettings.qml @@ -2,8 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import qs.Commons -import qs.Widgets import qs.Services.System +import qs.Widgets ColumnLayout { id: root @@ -18,31 +18,37 @@ ColumnLayout { property string valueColorName: widgetData.colorName !== undefined ? widgetData.colorName : widgetMetadata.colorName function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.colorName = valueColorName - return settings + var settings = Object.assign({}, widgetData || {}); + settings.colorName = valueColorName; + return settings; } NComboBox { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.audio-visualizer.color-name.label") description: I18n.tr("bar.widget-settings.audio-visualizer.color-name.description") - model: [{ + model: [ + { "key": "primary", "name": I18n.tr("options.colors.primary") - }, { + }, + { "key": "secondary", "name": I18n.tr("options.colors.secondary") - }, { + }, + { "key": "tertiary", "name": I18n.tr("options.colors.tertiary") - }, { + }, + { "key": "onSurface", "name": I18n.tr("options.colors.onSurface") - }, { + }, + { "key": "error", "name": I18n.tr("options.colors.error") - }] + } + ] currentKey: root.valueColorName onSelected: key => root.valueColorName = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/SpacerSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/SpacerSettings.qml index 423f0d65..0bffb2e3 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/SpacerSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/SpacerSettings.qml @@ -13,9 +13,9 @@ ColumnLayout { property var widgetMetadata: null function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.width = parseInt(widthInput.text) || widgetMetadata.width - return settings + var settings = Object.assign({}, widgetData || {}); + settings.width = parseInt(widthInput.text) || widgetMetadata.width; + return settings; } NTextInput { diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml index 86c65b96..58bed7a9 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml @@ -22,16 +22,16 @@ ColumnLayout { property bool valueShowDiskUsage: widgetData.showDiskUsage !== undefined ? widgetData.showDiskUsage : widgetMetadata.showDiskUsage function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.usePrimaryColor = valueUsePrimaryColor - settings.showCpuUsage = valueShowCpuUsage - settings.showCpuTemp = valueShowCpuTemp - settings.showMemoryUsage = valueShowMemoryUsage - settings.showMemoryAsPercent = valueShowMemoryAsPercent - settings.showNetworkStats = valueShowNetworkStats - settings.showDiskUsage = valueShowDiskUsage + var settings = Object.assign({}, widgetData || {}); + settings.usePrimaryColor = valueUsePrimaryColor; + settings.showCpuUsage = valueShowCpuUsage; + settings.showCpuTemp = valueShowCpuTemp; + settings.showMemoryUsage = valueShowMemoryUsage; + settings.showMemoryAsPercent = valueShowMemoryAsPercent; + settings.showNetworkStats = valueShowNetworkStats; + settings.showDiskUsage = valueShowDiskUsage; - return settings + return settings; } NToggle { diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarGroupedSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarGroupedSettings.qml index a849385b..ac9d46ef 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarGroupedSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarGroupedSettings.qml @@ -19,26 +19,29 @@ ColumnLayout { property bool valueColorizeIcons: widgetData.colorizeIcons !== undefined ? widgetData.colorizeIcons : (widgetMetadata ? widgetMetadata.colorizeIcons : false) function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.labelMode = valueLabelMode - settings.hideUnoccupied = valueHideUnoccupied - settings.showWorkspaceNumbers = valueShowWorkspaceNumbers - settings.showNumbersOnlyWhenOccupied = valueShowNumbersOnlyWhenOccupied - settings.colorizeIcons = valueColorizeIcons - return settings + var settings = Object.assign({}, widgetData || {}); + settings.labelMode = valueLabelMode; + settings.hideUnoccupied = valueHideUnoccupied; + settings.showWorkspaceNumbers = valueShowWorkspaceNumbers; + settings.showNumbersOnlyWhenOccupied = valueShowNumbersOnlyWhenOccupied; + settings.colorizeIcons = valueColorizeIcons; + return settings; } NComboBox { id: labelModeCombo label: I18n.tr("bar.widget-settings.workspace.label-mode.label") description: I18n.tr("bar.widget-settings.workspace.label-mode.description") - model: [{ + model: [ + { "key": "none", "name": I18n.tr("options.workspace-labels.none") - }, { + }, + { "key": "index", "name": I18n.tr("options.workspace-labels.index") - }, { + }, + { "key": "name", "name": I18n.tr("options.workspace-labels.name") }, { diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarSettings.qml index 825d32d5..e7c688f4 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/TaskbarSettings.qml @@ -20,35 +20,39 @@ ColumnLayout { Component.onCompleted: { if (widgetData && widgetData.hideMode !== undefined) { - valueHideMode = widgetData.hideMode + valueHideMode = widgetData.hideMode; } else if (widgetMetadata && widgetMetadata.hideMode !== undefined) { - valueHideMode = widgetMetadata.hideMode + valueHideMode = widgetMetadata.hideMode; } } function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.hideMode = valueHideMode - settings.onlySameOutput = valueOnlySameOutput - settings.onlyActiveWorkspaces = valueOnlyActiveWorkspaces - settings.colorizeIcons = valueColorizeIcons - return settings + var settings = Object.assign({}, widgetData || {}); + settings.hideMode = valueHideMode; + settings.onlySameOutput = valueOnlySameOutput; + settings.onlyActiveWorkspaces = valueOnlyActiveWorkspaces; + settings.colorizeIcons = valueColorizeIcons; + return settings; } NComboBox { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.taskbar.hide-mode.label") description: I18n.tr("bar.widget-settings.taskbar.hide-mode.description") - model: [{ + model: [ + { "key": "visible", "name": I18n.tr("options.hide-modes.visible") - }, { + }, + { "key": "hidden", "name": I18n.tr("options.hide-modes.hidden") - }, { + }, + { "key": "transparent", "name": I18n.tr("options.hide-modes.transparent") - }] + } + ] currentKey: root.valueHideMode onSelected: key => root.valueHideMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/TraySettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/TraySettings.qml index a628863d..a9b0c23e 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/TraySettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/TraySettings.qml @@ -24,7 +24,7 @@ ColumnLayout { for (var i = 0; i < localBlacklist.length; i++) { blacklistModel.append({ "rule": localBlacklist[i] - }) + }); } } @@ -66,19 +66,19 @@ ColumnLayout { buttonIcon: "add" onButtonClicked: { if (newRuleInput.text.length > 0) { - var newRule = newRuleInput.text.trim() - var exists = false + var newRule = newRuleInput.text.trim(); + var exists = false; for (var i = 0; i < blacklistModel.count; i++) { if (blacklistModel.get(i).rule === newRule) { - exists = true - break + exists = true; + break; } } if (!exists) { blacklistModel.append({ "rule": newRule - }) - newRuleInput.text = "" + }); + newRuleInput.text = ""; } } } @@ -131,7 +131,7 @@ ColumnLayout { colorBgHover: Color.mError colorFgHover: Color.mOnError onClicked: { - blacklistModel.remove(index) + blacklistModel.remove(index); } } } @@ -140,16 +140,16 @@ ColumnLayout { // This function will be called by the dialog to get the new settings function saveSettings() { - var newBlacklist = [] + var newBlacklist = []; for (var i = 0; i < blacklistModel.count; i++) { - newBlacklist.push(blacklistModel.get(i).rule) + newBlacklist.push(blacklistModel.get(i).rule); } // Return the updated settings for this widget instance - var settings = Object.assign({}, widgetData || {}) - settings.blacklist = newBlacklist - settings.colorizeIcons = root.valueColorizeIcons - settings.drawerEnabled = root.valueDrawerEnabled - return settings + var settings = Object.assign({}, widgetData || {}); + settings.blacklist = newBlacklist; + settings.colorizeIcons = root.valueColorizeIcons; + settings.drawerEnabled = root.valueDrawerEnabled; + return settings; } } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/VolumeSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/VolumeSettings.qml index 09032661..3f8d6f1b 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/VolumeSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/VolumeSettings.qml @@ -16,25 +16,29 @@ ColumnLayout { property string valueDisplayMode: widgetData.displayMode !== undefined ? widgetData.displayMode : widgetMetadata.displayMode function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.displayMode = valueDisplayMode - return settings + var settings = Object.assign({}, widgetData || {}); + settings.displayMode = valueDisplayMode; + return settings; } NComboBox { label: I18n.tr("bar.widget-settings.volume.display-mode.label") description: I18n.tr("bar.widget-settings.volume.display-mode.description") minimumWidth: 134 - model: [{ + model: [ + { "key": "onhover", "name": I18n.tr("options.display-mode.on-hover") - }, { + }, + { "key": "alwaysShow", "name": I18n.tr("options.display-mode.always-show") - }, { + }, + { "key": "alwaysHide", "name": I18n.tr("options.display-mode.always-hide") - }] + } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/WiFiSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/WiFiSettings.qml index d6548476..72353f4d 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/WiFiSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/WiFiSettings.qml @@ -15,25 +15,29 @@ ColumnLayout { property string valueDisplayMode: widgetData.displayMode !== undefined ? widgetData.displayMode : widgetMetadata.displayMode function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.displayMode = valueDisplayMode - return settings + var settings = Object.assign({}, widgetData || {}); + settings.displayMode = valueDisplayMode; + return settings; } NComboBox { label: I18n.tr("bar.widget-settings.battery.display-mode.label") description: I18n.tr("bar.widget-settings.battery.display-mode.description") minimumWidth: 134 - model: [{ + model: [ + { "key": "onhover", "name": I18n.tr("options.display-mode.on-hover") - }, { + }, + { "key": "alwaysShow", "name": I18n.tr("options.display-mode.always-show") - }, { + }, + { "key": "alwaysHide", "name": I18n.tr("options.display-mode.always-hide") - }] + } + ] currentKey: root.valueDisplayMode onSelected: key => root.valueDisplayMode = key } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/WorkspaceSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/WorkspaceSettings.qml index 83d0bbad..5800cff6 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/WorkspaceSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/WorkspaceSettings.qml @@ -17,27 +17,31 @@ ColumnLayout { property int valueCharacterCount: widgetData.characterCount !== undefined ? widgetData.characterCount : widgetMetadata.characterCount function saveSettings() { - var settings = Object.assign({}, widgetData || {}) - settings.labelMode = valueLabelMode - settings.hideUnoccupied = valueHideUnoccupied - settings.characterCount = valueCharacterCount - return settings + var settings = Object.assign({}, widgetData || {}); + settings.labelMode = valueLabelMode; + settings.hideUnoccupied = valueHideUnoccupied; + settings.characterCount = valueCharacterCount; + return settings; } NComboBox { id: labelModeCombo label: I18n.tr("bar.widget-settings.workspace.label-mode.label") description: I18n.tr("bar.widget-settings.workspace.label-mode.description") - model: [{ + model: [ + { "key": "none", "name": I18n.tr("options.workspace-labels.none") - }, { + }, + { "key": "index", "name": I18n.tr("options.workspace-labels.index") - }, { + }, + { "key": "name", "name": I18n.tr("options.workspace-labels.name") - }] + } + ] currentKey: widgetData.labelMode || widgetMetadata.labelMode onSelected: key => valueLabelMode = key minimumWidth: 200 diff --git a/Modules/Panels/Settings/ControlCenter/ControlCenterWidgetSettingsDialog.qml b/Modules/Panels/Settings/ControlCenter/ControlCenterWidgetSettingsDialog.qml index 8ebea72e..709e0835 100644 --- a/Modules/Panels/Settings/ControlCenter/ControlCenterWidgetSettingsDialog.qml +++ b/Modules/Panels/Settings/ControlCenter/ControlCenterWidgetSettingsDialog.qml @@ -2,8 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import qs.Commons -import qs.Widgets import qs.Services.UI +import qs.Widgets // Widget Settings Dialog Component Popup { @@ -24,7 +24,7 @@ Popup { onOpened: { if (widgetData && widgetId) { - loadWidgetSettings() + loadWidgetSettings(); } } @@ -94,9 +94,9 @@ Popup { icon: "check" onClicked: { if (settingsLoader.item && settingsLoader.item.saveSettings) { - var newSettings = settingsLoader.item.saveSettings() - root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings) - root.close() + var newSettings = settingsLoader.item.saveSettings(); + root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings); + root.close(); } } } @@ -106,14 +106,14 @@ Popup { function loadWidgetSettings() { const widgetSettingsMap = { "CustomButton": "WidgetSettings/CustomButtonSettings.qml" - } + }; - const source = widgetSettingsMap[widgetId] + const source = widgetSettingsMap[widgetId]; if (source) { settingsLoader.setSource(source, { "widgetData": widgetData, "widgetMetadata": ControlCenterWidgetRegistry.widgetMetadata[widgetId] - }) + }); } } } diff --git a/Modules/Panels/Settings/ControlCenter/WidgetSettings/CustomButtonSettings.qml b/Modules/Panels/Settings/ControlCenter/WidgetSettings/CustomButtonSettings.qml index 3cd0cb9b..f26f46a6 100644 --- a/Modules/Panels/Settings/ControlCenter/WidgetSettings/CustomButtonSettings.qml +++ b/Modules/Panels/Settings/ControlCenter/WidgetSettings/CustomButtonSettings.qml @@ -1,6 +1,6 @@ +import QtQml.Models import QtQuick import QtQuick.Layouts -import QtQml.Models import qs.Commons import qs.Widgets @@ -23,34 +23,34 @@ ColumnLayout { property bool enableOnStateLogic: (widgetData && widgetData.enableOnStateLogic !== undefined) ? widgetData.enableOnStateLogic : widgetMetadata.enableOnStateLogic Component.onCompleted: { - stateChecksJson = (widgetData && widgetData.stateChecksJson !== undefined) ? widgetData.stateChecksJson : widgetMetadata.stateChecksJson || "[]" + stateChecksJson = (widgetData && widgetData.stateChecksJson !== undefined) ? widgetData.stateChecksJson : widgetMetadata.stateChecksJson || "[]"; try { - var initialChecks = JSON.parse(stateChecksJson) + var initialChecks = JSON.parse(stateChecksJson); if (initialChecks && Array.isArray(initialChecks)) { for (var i = 0; i < initialChecks.length; i++) { - var item = initialChecks[i] + var item = initialChecks[i]; if (item && typeof item === "object") { _settings._stateChecksListModel.append({ "command": item.command || "", "icon": item.icon || "" - }) + }); } else { - console.warn("⚠️ Invalid stateChecks entry at index " + i + ":", item) + console.warn("⚠️ Invalid stateChecks entry at index " + i + ":", item); } } } } catch (e) { - console.error("CustomButtonSettings: Failed to parse stateChecksJson:", e.message) + console.error("CustomButtonSettings: Failed to parse stateChecksJson:", e.message); } } } function saveSettings() { - var savedStateChecksArray = [] + var savedStateChecksArray = []; for (var i = 0; i < _settings._stateChecksListModel.count; i++) { - savedStateChecksArray.push(_settings._stateChecksListModel.get(i)) + savedStateChecksArray.push(_settings._stateChecksListModel.get(i)); } - _settings.stateChecksJson = JSON.stringify(savedStateChecksArray) + _settings.stateChecksJson = JSON.stringify(savedStateChecksArray); return { "id": widgetData.id, @@ -61,7 +61,7 @@ ColumnLayout { "stateChecksJson": _settings.stateChecksJson, "generalTooltipText": _settings.generalTooltipText, "enableOnStateLogic": _settings.enableOnStateLogic - } + }; } RowLayout { @@ -89,7 +89,7 @@ ColumnLayout { id: iconPicker initialIcon: _settings.icon onIconSelected: function (iconName) { - _settings.icon = iconName + _settings.icon = iconName; } } @@ -210,7 +210,7 @@ ColumnLayout { _settings._stateChecksListModel.set(currentIndex, { "command": model.command, "icon": iconName - }) + }); } } diff --git a/Modules/Panels/Settings/SettingsPanel.qml b/Modules/Panels/Settings/SettingsPanel.qml index d0fbbfc4..e56b070c 100644 --- a/Modules/Panels/Settings/SettingsPanel.qml +++ b/Modules/Panels/Settings/SettingsPanel.qml @@ -2,9 +2,9 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell -import qs.Modules.Panels.Settings.Tabs import qs.Commons import qs.Modules.MainScreen +import qs.Modules.Panels.Settings.Tabs import qs.Services.System import qs.Widgets @@ -30,31 +30,31 @@ SmartPanel { onAttachToBarChanged: { if (isPanelOpen) { - Qt.callLater(root.setPosition) + Qt.callLater(root.setPosition); } } onBarPositionChanged: { if (isPanelOpen) { - Qt.callLater(root.setPosition) + Qt.callLater(root.setPosition); } } onBarFloatingChanged: { if (isPanelOpen) { - Qt.callLater(root.setPosition) + Qt.callLater(root.setPosition); } } onBarMarginHChanged: { if (isPanelOpen) { - Qt.callLater(root.setPosition) + Qt.callLater(root.setPosition); } } onBarMarginVChanged: { if (isPanelOpen) { - Qt.callLater(root.setPosition) + Qt.callLater(root.setPosition); } } @@ -88,7 +88,7 @@ SmartPanel { property var activeScrollView: null Component.onCompleted: { - updateTabsModel() + updateTabsModel(); } Component { @@ -174,208 +174,229 @@ SmartPanel { // Order *DOES* matter function updateTabsModel() { - let newTabs = [{ - "id": SettingsPanel.Tab.General, - "label": "settings.general.title", - "icon": "settings-general", - "source": generalTab - }, { - "id": SettingsPanel.Tab.UserInterface, - "label": "settings.user-interface.title", - "icon": "settings-user-interface", - "source": userInterfaceTab - }, { - "id": SettingsPanel.Tab.ColorScheme, - "label": "settings.color-scheme.title", - "icon": "settings-color-scheme", - "source": colorSchemeTab - }, { - "id": SettingsPanel.Tab.Wallpaper, - "label": "settings.wallpaper.title", - "icon": "settings-wallpaper", - "source": wallpaperTab - }, { - "id": SettingsPanel.Tab.Bar, - "label": "settings.bar.title", - "icon": "settings-bar", - "source": barTab - }, { - "id": SettingsPanel.Tab.Dock, - "label": "settings.dock.title", - "icon": "settings-dock", - "source": dockTab - }, { - "id": SettingsPanel.Tab.ControlCenter, - "label": "settings.control-center.title", - "icon": "settings-control-center", - "source": controlCenterTab - }, { - "id": SettingsPanel.Tab.Launcher, - "label": "settings.launcher.title", - "icon": "settings-launcher", - "source": launcherTab - }, { - "id": SettingsPanel.Tab.Notifications, - "label": "settings.notifications.title", - "icon": "settings-notifications", - "source": notificationsTab - }, { - "id": SettingsPanel.Tab.OSD, - "label": "settings.osd.title", - "icon": "settings-osd", - "source": osdTab - }, { - "id": SettingsPanel.Tab.LockScreen, - "label": "settings.lock-screen.title", - "icon": "settings-lock-screen", - "source": lockScreenTab - }, { - "id": SettingsPanel.Tab.SessionMenu, - "label": "settings.session-menu.title", - "icon": "settings-session-menu", - "source": sessionMenuTab - }, { - "id": SettingsPanel.Tab.Audio, - "label": "settings.audio.title", - "icon": "settings-audio", - "source": audioTab - }, { - "id": SettingsPanel.Tab.Display, - "label": "settings.display.title", - "icon": "settings-display", - "source": displayTab - }, { - "id": SettingsPanel.Tab.Network, - "label": "settings.network.title", - "icon": "settings-network", - "source": networkTab - }, { - "id": SettingsPanel.Tab.Location, - "label": "settings.location.title", - "icon": "settings-location", - "source": locationTab - }, { - "id": SettingsPanel.Tab.ScreenRecorder, - "label": "settings.screen-recorder.title", - "icon": "settings-screen-recorder", - "source": screenRecorderTab - }, { - "id": SettingsPanel.Tab.SystemMonitor, - "label": "settings.system-monitor.title", - "icon": "settings-system-monitor", - "source": systemMonitorTab - }, { - "id": SettingsPanel.Tab.Hooks, - "label": "settings.hooks.title", - "icon": "settings-hooks", - "source": hooksTab - }, { - "id": SettingsPanel.Tab.About, - "label": "settings.about.title", - "icon": "settings-about", - "source": aboutTab - }] + let newTabs = [ + { + "id": SettingsPanel.Tab.General, + "label": "settings.general.title", + "icon": "settings-general", + "source": generalTab + }, + { + "id": SettingsPanel.Tab.UserInterface, + "label": "settings.user-interface.title", + "icon": "settings-user-interface", + "source": userInterfaceTab + }, + { + "id": SettingsPanel.Tab.ColorScheme, + "label": "settings.color-scheme.title", + "icon": "settings-color-scheme", + "source": colorSchemeTab + }, + { + "id": SettingsPanel.Tab.Wallpaper, + "label": "settings.wallpaper.title", + "icon": "settings-wallpaper", + "source": wallpaperTab + }, + { + "id": SettingsPanel.Tab.Bar, + "label": "settings.bar.title", + "icon": "settings-bar", + "source": barTab + }, + { + "id": SettingsPanel.Tab.Dock, + "label": "settings.dock.title", + "icon": "settings-dock", + "source": dockTab + }, + { + "id": SettingsPanel.Tab.ControlCenter, + "label": "settings.control-center.title", + "icon": "settings-control-center", + "source": controlCenterTab + }, + { + "id": SettingsPanel.Tab.Launcher, + "label": "settings.launcher.title", + "icon": "settings-launcher", + "source": launcherTab + }, + { + "id": SettingsPanel.Tab.Notifications, + "label": "settings.notifications.title", + "icon": "settings-notifications", + "source": notificationsTab + }, + { + "id": SettingsPanel.Tab.OSD, + "label": "settings.osd.title", + "icon": "settings-osd", + "source": osdTab + }, + { + "id": SettingsPanel.Tab.LockScreen, + "label": "settings.lock-screen.title", + "icon": "settings-lock-screen", + "source": lockScreenTab + }, + { + "id": SettingsPanel.Tab.SessionMenu, + "label": "settings.session-menu.title", + "icon": "settings-session-menu", + "source": sessionMenuTab + }, + { + "id": SettingsPanel.Tab.Audio, + "label": "settings.audio.title", + "icon": "settings-audio", + "source": audioTab + }, + { + "id": SettingsPanel.Tab.Display, + "label": "settings.display.title", + "icon": "settings-display", + "source": displayTab + }, + { + "id": SettingsPanel.Tab.Network, + "label": "settings.network.title", + "icon": "settings-network", + "source": networkTab + }, + { + "id": SettingsPanel.Tab.Location, + "label": "settings.location.title", + "icon": "settings-location", + "source": locationTab + }, + { + "id": SettingsPanel.Tab.ScreenRecorder, + "label": "settings.screen-recorder.title", + "icon": "settings-screen-recorder", + "source": screenRecorderTab + }, + { + "id": SettingsPanel.Tab.SystemMonitor, + "label": "settings.system-monitor.title", + "icon": "settings-system-monitor", + "source": systemMonitorTab + }, + { + "id": SettingsPanel.Tab.Hooks, + "label": "settings.hooks.title", + "icon": "settings-hooks", + "source": hooksTab + }, + { + "id": SettingsPanel.Tab.About, + "label": "settings.about.title", + "icon": "settings-about", + "source": aboutTab + } + ]; - root.tabsModel = newTabs // Assign the generated list to the model + root.tabsModel = newTabs; // Assign the generated list to the model } // When the panel opens, choose the appropriate tab onOpened: { // Run program availability checks every time settings opens - ProgramCheckerService.checkAllPrograms() - updateTabsModel() + ProgramCheckerService.checkAllPrograms(); + updateTabsModel(); - var initialIndex = SettingsPanel.Tab.General + var initialIndex = SettingsPanel.Tab.General; if (root.requestedTab !== null) { for (var i = 0; i < root.tabsModel.length; i++) { if (root.tabsModel[i].id === root.requestedTab) { - initialIndex = i - break + initialIndex = i; + break; } } } // Now that the UI is settled, set the current tab index. - root.currentTabIndex = initialIndex + root.currentTabIndex = initialIndex; } // Add scroll functions function scrollDown() { if (activeScrollView && activeScrollView.ScrollBar.vertical) { - const scrollBar = activeScrollView.ScrollBar.vertical - const stepSize = activeScrollView.height * 0.1 // Scroll 10% of viewport - scrollBar.position = Math.min(scrollBar.position + stepSize / activeScrollView.contentHeight, 1.0 - scrollBar.size) + const scrollBar = activeScrollView.ScrollBar.vertical; + const stepSize = activeScrollView.height * 0.1; // Scroll 10% of viewport + scrollBar.position = Math.min(scrollBar.position + stepSize / activeScrollView.contentHeight, 1.0 - scrollBar.size); } } function scrollUp() { if (activeScrollView && activeScrollView.ScrollBar.vertical) { - const scrollBar = activeScrollView.ScrollBar.vertical - const stepSize = activeScrollView.height * 0.1 // Scroll 10% of viewport - scrollBar.position = Math.max(scrollBar.position - stepSize / activeScrollView.contentHeight, 0) + const scrollBar = activeScrollView.ScrollBar.vertical; + const stepSize = activeScrollView.height * 0.1; // Scroll 10% of viewport + scrollBar.position = Math.max(scrollBar.position - stepSize / activeScrollView.contentHeight, 0); } } function scrollPageDown() { if (activeScrollView && activeScrollView.ScrollBar.vertical) { - const scrollBar = activeScrollView.ScrollBar.vertical - const pageSize = activeScrollView.height * 0.9 // Scroll 90% of viewport - scrollBar.position = Math.min(scrollBar.position + pageSize / activeScrollView.contentHeight, 1.0 - scrollBar.size) + const scrollBar = activeScrollView.ScrollBar.vertical; + const pageSize = activeScrollView.height * 0.9; // Scroll 90% of viewport + scrollBar.position = Math.min(scrollBar.position + pageSize / activeScrollView.contentHeight, 1.0 - scrollBar.size); } } function scrollPageUp() { if (activeScrollView && activeScrollView.ScrollBar.vertical) { - const scrollBar = activeScrollView.ScrollBar.vertical - const pageSize = activeScrollView.height * 0.9 // Scroll 90% of viewport - scrollBar.position = Math.max(scrollBar.position - pageSize / activeScrollView.contentHeight, 0) + const scrollBar = activeScrollView.ScrollBar.vertical; + const pageSize = activeScrollView.height * 0.9; // Scroll 90% of viewport + scrollBar.position = Math.max(scrollBar.position - pageSize / activeScrollView.contentHeight, 0); } } // Add navigation functions function selectNextTab() { if (tabsModel.length > 0) { - currentTabIndex = (currentTabIndex + 1) % tabsModel.length + currentTabIndex = (currentTabIndex + 1) % tabsModel.length; } } function selectPreviousTab() { if (tabsModel.length > 0) { - currentTabIndex = (currentTabIndex - 1 + tabsModel.length) % tabsModel.length + currentTabIndex = (currentTabIndex - 1 + tabsModel.length) % tabsModel.length; } } // Override keyboard handlers from SmartPanel function onTabPressed() { - selectNextTab() + selectNextTab(); } function onBackTabPressed() { - selectPreviousTab() + selectPreviousTab(); } function onUpPressed() { - scrollUp() + scrollUp(); } function onDownPressed() { - scrollDown() + scrollDown(); } function onPageUpPressed() { - scrollPageUp() + scrollPageUp(); } function onPageDownPressed() { - scrollPageDown() + scrollPageDown(); } function onCtrlJPressed() { - scrollDown() + scrollDown(); } function onCtrlKPressed() { - scrollUp() + scrollUp(); } panelContent: Rectangle { @@ -481,7 +502,7 @@ SmartPanel { onCurrentIndexChanged: { if (currentIndex !== root.currentTabIndex) { - root.currentTabIndex = currentIndex + root.currentTabIndex = currentIndex; } } @@ -489,8 +510,8 @@ SmartPanel { target: root function onCurrentTabIndexChanged() { if (sidebarList.currentIndex !== root.currentTabIndex) { - sidebarList.currentIndex = root.currentTabIndex - sidebarList.positionViewAtIndex(root.currentTabIndex, ListView.Contain) + sidebarList.currentIndex = root.currentTabIndex; + sidebarList.positionViewAtIndex(root.currentTabIndex, ListView.Contain); } } } @@ -566,9 +587,9 @@ SmartPanel { onStatusChanged: { if (status === Loader.Ready && item) { // Find and store reference to the ScrollView - const scrollView = item.children[0] + const scrollView = item.children[0]; if (scrollView && scrollView.toString().includes("ScrollView")) { - root.activeScrollView = scrollView + root.activeScrollView = scrollView; } } } @@ -587,7 +608,7 @@ SmartPanel { verticalPolicy: ScrollBar.AsNeeded padding: Style.marginL Component.onCompleted: { - root.activeScrollView = scrollView + root.activeScrollView = scrollView; } Loader { diff --git a/Modules/Panels/Settings/Tabs/AboutTab.qml b/Modules/Panels/Settings/Tabs/AboutTab.qml index b3463bc3..3c2211ca 100644 --- a/Modules/Panels/Settings/Tabs/AboutTab.qml +++ b/Modules/Panels/Settings/Tabs/AboutTab.qml @@ -58,27 +58,27 @@ ColumnLayout { NButton { visible: { if (root.latestVersion === "Unknown") - return false + return false; - const latest = root.latestVersion.replace("v", "").split(".") - const current = root.currentVersion.replace("v", "").split(".") + const latest = root.latestVersion.replace("v", "").split("."); + const current = root.currentVersion.replace("v", "").split("."); for (var i = 0; i < Math.max(latest.length, current.length); i++) { - const l = parseInt(latest[i] || "0") - const c = parseInt(current[i] || "0") + const l = parseInt(latest[i] || "0"); + const c = parseInt(current[i] || "0"); if (l > c) - return true + return true; if (l < c) - return false + return false; } - return false + return false; } icon: "download" text: I18n.tr("settings.about.noctalia.download-latest") outlined: !hovered fontSize: Style.fontSizeXS onClicked: { - Quickshell.execDetached(["xdg-open", "https://github.com/Ly-sec/Noctalia/releases/latest"]) + Quickshell.execDetached(["xdg-open", "https://github.com/Ly-sec/Noctalia/releases/latest"]); } } } @@ -126,8 +126,8 @@ ColumnLayout { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { - Quickshell.execDetached(["xdg-open", "https://ko-fi.com/lysec"]) - ToastService.showNotice(I18n.tr("settings.about.support"), I18n.tr("toast.kofi.opened")) + Quickshell.execDetached(["xdg-open", "https://ko-fi.com/lysec"]); + ToastService.showNotice(I18n.tr("settings.about.support"), I18n.tr("toast.kofi.opened")); } } } @@ -157,10 +157,10 @@ ColumnLayout { Layout.preferredWidth: cellWidth * columnsCount Layout.preferredHeight: { if (root.contributors.length === 0) - return 0 + return 0; - const rows = Math.ceil(root.contributors.length / columnsCount) - return rows * cellHeight + const rows = Math.ceil(root.contributors.length / columnsCount); + return rows * cellHeight; } cellWidth: Math.round(Style.baseWidgetSize * 7) cellHeight: Math.round(Style.baseWidgetSize * 2.5) @@ -233,7 +233,7 @@ ColumnLayout { cursorShape: Qt.PointingHandCursor onClicked: { if (modelData.html_url) - Quickshell.execDetached(["xdg-open", modelData.html_url]) + Quickshell.execDetached(["xdg-open", modelData.html_url]); } } } diff --git a/Modules/Panels/Settings/Tabs/AudioTab.qml b/Modules/Panels/Settings/Tabs/AudioTab.qml index d47fe949..34d7ab17 100644 --- a/Modules/Panels/Settings/Tabs/AudioTab.qml +++ b/Modules/Panels/Settings/Tabs/AudioTab.qml @@ -20,7 +20,7 @@ ColumnLayout { Connections { target: AudioService.sink?.audio ? AudioService.sink?.audio : null function onVolumeChanged() { - localVolume = AudioService.volume + localVolume = AudioService.volume; } } @@ -43,7 +43,7 @@ ColumnLayout { repeat: true onTriggered: { if (Math.abs(localVolume - AudioService.volume) >= 0.01) { - AudioService.setVolume(localVolume) + AudioService.setVolume(localVolume); } } } @@ -70,7 +70,7 @@ ColumnLayout { checked: AudioService.muted onToggled: checked => { if (AudioService.sink && AudioService.sink.audio) { - AudioService.sink.audio.muted = checked + AudioService.sink.audio.muted = checked; } } } @@ -181,8 +181,8 @@ ColumnLayout { text: modelData.description checked: AudioService.sink?.id === modelData.id onClicked: { - AudioService.setAudioSink(modelData) - localVolume = AudioService.volume + AudioService.setAudioSink(modelData); + localVolume = AudioService.volume; } Layout.fillWidth: true } @@ -242,8 +242,8 @@ ColumnLayout { placeholderText: I18n.tr("settings.audio.media.primary-player.placeholder") text: Settings.data.audio.preferredPlayer onTextChanged: { - Settings.data.audio.preferredPlayer = text - MediaService.updateCurrentPlayer() + Settings.data.audio.preferredPlayer = text; + MediaService.updateCurrentPlayer(); } } @@ -260,13 +260,13 @@ ColumnLayout { buttonIcon: "add" Layout.fillWidth: true onButtonClicked: { - const val = (blacklistInput.text || "").trim() + const val = (blacklistInput.text || "").trim(); if (val !== "") { - const arr = (Settings.data.audio.mprisBlacklist || []) + const arr = (Settings.data.audio.mprisBlacklist || []); if (!arr.find(x => String(x).toLowerCase() === val.toLowerCase())) { - Settings.data.audio.mprisBlacklist = [...arr, val] - blacklistInput.text = "" - MediaService.updateCurrentPlayer() + Settings.data.audio.mprisBlacklist = [...arr, val]; + blacklistInput.text = ""; + MediaService.updateCurrentPlayer(); } } } @@ -310,12 +310,12 @@ ColumnLayout { Layout.alignment: Qt.AlignVCenter Layout.rightMargin: Style.marginXS onClicked: { - const arr = (Settings.data.audio.mprisBlacklist || []) - const idx = arr.findIndex(x => String(x) === modelData) + const arr = (Settings.data.audio.mprisBlacklist || []); + const idx = arr.findIndex(x => String(x) === modelData); if (idx >= 0) { - arr.splice(idx, 1) - Settings.data.audio.mprisBlacklist = arr - MediaService.updateCurrentPlayer() + arr.splice(idx, 1); + Settings.data.audio.mprisBlacklist = arr; + MediaService.updateCurrentPlayer(); } } } @@ -333,19 +333,24 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.audio.media.visualizer-type.label") description: I18n.tr("settings.audio.media.visualizer-type.description") - model: [{ + model: [ + { "key": "none", "name": I18n.tr("options.visualizer-types.none") - }, { + }, + { "key": "linear", "name": I18n.tr("options.visualizer-types.linear") - }, { + }, + { "key": "mirrored", "name": I18n.tr("options.visualizer-types.mirrored") - }, { + }, + { "key": "wave", "name": I18n.tr("options.visualizer-types.wave") - }] + } + ] currentKey: Settings.data.audio.visualizerType onSelected: key => Settings.data.audio.visualizerType = key } @@ -353,13 +358,16 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.audio.media.visualizer-quality.label") description: I18n.tr("settings.audio.media.visualizer-quality.description") - model: [{ + model: [ + { "key": "low", "name": I18n.tr("options.visualizer-quality.low") - }, { + }, + { "key": "high", "name": I18n.tr("options.visualizer-quality.high") - }] + } + ] currentKey: Settings.data.audio.visualizerQuality onSelected: key => Settings.data.audio.visualizerQuality = key } @@ -367,42 +375,50 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.audio.media.frame-rate.label") description: I18n.tr("settings.audio.media.frame-rate.description") - model: [{ + model: [ + { "key": "30", "name": I18n.tr("options.frame-rates.fps", { "fps": "30" }) - }, { + }, + { "key": "60", "name": I18n.tr("options.frame-rates.fps", { "fps": "60" }) - }, { + }, + { "key": "100", "name": I18n.tr("options.frame-rates.fps", { "fps": "100" }) - }, { + }, + { "key": "120", "name": I18n.tr("options.frame-rates.fps", { "fps": "120" }) - }, { + }, + { "key": "144", "name": I18n.tr("options.frame-rates.fps", { "fps": "144" }) - }, { + }, + { "key": "165", "name": I18n.tr("options.frame-rates.fps", { "fps": "165" }) - }, { + }, + { "key": "240", "name": I18n.tr("options.frame-rates.fps", { "fps": "240" }) - }] + } + ] currentKey: Settings.data.audio.cavaFrameRate onSelected: key => Settings.data.audio.cavaFrameRate = key } diff --git a/Modules/Panels/Settings/Tabs/BarTab.qml b/Modules/Panels/Settings/Tabs/BarTab.qml index f39d11a9..5ba61a05 100644 --- a/Modules/Panels/Settings/Tabs/BarTab.qml +++ b/Modules/Panels/Settings/Tabs/BarTab.qml @@ -13,15 +13,15 @@ ColumnLayout { // Helper functions to update arrays immutably function addMonitor(list, name) { - const arr = (list || []).slice() + const arr = (list || []).slice(); if (!arr.includes(name)) - arr.push(name) - return arr + arr.push(name); + return arr; } function removeMonitor(list, name) { return (list || []).filter(function (n) { - return n !== name - }) + return n !== name; + }); } NHeader { @@ -33,19 +33,24 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.bar.appearance.position.label") description: I18n.tr("settings.bar.appearance.position.description") - model: [{ + model: [ + { "key": "top", "name": I18n.tr("options.bar.position.top") - }, { + }, + { "key": "bottom", "name": I18n.tr("options.bar.position.bottom") - }, { + }, + { "key": "left", "name": I18n.tr("options.bar.position.left") - }, { + }, + { "key": "right", "name": I18n.tr("options.bar.position.right") - }] + } + ] currentKey: Settings.data.bar.position onSelected: key => Settings.data.bar.position = key } @@ -54,19 +59,24 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.bar.appearance.density.label") description: I18n.tr("settings.bar.appearance.density.description") - model: [{ + model: [ + { "key": "mini", "name": I18n.tr("options.bar.density.mini") - }, { + }, + { "key": "compact", "name": I18n.tr("options.bar.density.compact") - }, { + }, + { "key": "default", "name": I18n.tr("options.bar.density.default") - }, { + }, + { "key": "comfortable", "name": I18n.tr("options.bar.density.comfortable") - }] + } + ] currentKey: Settings.data.bar.density onSelected: key => Settings.data.bar.density = key } @@ -85,13 +95,13 @@ ColumnLayout { description: I18n.tr("settings.bar.appearance.floating.description") checked: Settings.data.bar.floating onToggled: checked => { - Settings.data.bar.floating = checked + Settings.data.bar.floating = checked; if (checked) { // Disable outer corners when floating is enabled - Settings.data.bar.outerCorners = false + Settings.data.bar.outerCorners = false; } else { // Enable outer corners when floating is disabled - Settings.data.bar.outerCorners = true + Settings.data.bar.outerCorners = true; } } } @@ -274,20 +284,20 @@ ColumnLayout { Layout.fillWidth: true label: modelData.name || "Unknown" description: { - const compositorScale = CompositorService.getDisplayScale(modelData.name) + const compositorScale = CompositorService.getDisplayScale(modelData.name); I18n.tr("system.monitor-description", { "model": modelData.model, "width": modelData.width * compositorScale, "height": modelData.height * compositorScale, "scale": compositorScale - }) + }); } checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { - Settings.data.bar.monitors = addMonitor(Settings.data.bar.monitors, modelData.name) + Settings.data.bar.monitors = addMonitor(Settings.data.bar.monitors, modelData.name); } else { - Settings.data.bar.monitors = removeMonitor(Settings.data.bar.monitors, modelData.name) + Settings.data.bar.monitors = removeMonitor(Settings.data.bar.monitors, modelData.name); } } } @@ -304,29 +314,29 @@ ColumnLayout { function _addWidgetToSection(widgetId, section) { var newWidget = { "id": widgetId - } + }; if (BarWidgetRegistry.widgetHasUserSettings(widgetId)) { - var metadata = BarWidgetRegistry.widgetMetadata[widgetId] + var metadata = BarWidgetRegistry.widgetMetadata[widgetId]; if (metadata) { Object.keys(metadata).forEach(function (key) { if (key !== "allowUserSettings") { - newWidget[key] = metadata[key] + newWidget[key] = metadata[key]; } - }) + }); } } - Settings.data.bar.widgets[section].push(newWidget) + Settings.data.bar.widgets[section].push(newWidget); } function _removeWidgetFromSection(section, index) { if (index >= 0 && index < Settings.data.bar.widgets[section].length) { - var newArray = Settings.data.bar.widgets[section].slice() - var removedWidgets = newArray.splice(index, 1) - Settings.data.bar.widgets[section] = newArray + var newArray = Settings.data.bar.widgets[section].slice(); + var removedWidgets = newArray.splice(index, 1); + Settings.data.bar.widgets[section] = newArray; // Check that we still have a control center if (removedWidgets[0].id === "ControlCenter" && BarService.lookupWidget("ControlCenter") === undefined) { - ToastService.showWarning(I18n.tr("toast.missing-control-center.label"), I18n.tr("toast.missing-control-center.description"), 12000) + ToastService.showWarning(I18n.tr("toast.missing-control-center.label"), I18n.tr("toast.missing-control-center.description"), 12000); } } } @@ -335,36 +345,36 @@ ColumnLayout { if (fromIndex >= 0 && fromIndex < Settings.data.bar.widgets[section].length && toIndex >= 0 && toIndex < Settings.data.bar.widgets[section].length) { // Create a new array to avoid modifying the original - var newArray = Settings.data.bar.widgets[section].slice() - var item = newArray[fromIndex] - newArray.splice(fromIndex, 1) - newArray.splice(toIndex, 0, item) + var newArray = Settings.data.bar.widgets[section].slice(); + var item = newArray[fromIndex]; + newArray.splice(fromIndex, 1); + newArray.splice(toIndex, 0, item); - Settings.data.bar.widgets[section] = newArray + Settings.data.bar.widgets[section] = newArray; //Logger.i("BarTab", "Widget reordered. New array:", JSON.stringify(newArray)) } } function _updateWidgetSettingsInSection(section, index, settings) { // Update the widget settings in the Settings data - Settings.data.bar.widgets[section][index] = settings + Settings.data.bar.widgets[section][index] = settings; //Logger.i("BarTab", `Updated widget settings for ${settings.id} in ${section} section`) } function _moveWidgetBetweenSections(fromSection, index, toSection) { // Get the widget from the source section if (index >= 0 && index < Settings.data.bar.widgets[fromSection].length) { - var widget = Settings.data.bar.widgets[fromSection][index] + var widget = Settings.data.bar.widgets[fromSection][index]; // Remove from source section - var sourceArray = Settings.data.bar.widgets[fromSection].slice() - sourceArray.splice(index, 1) - Settings.data.bar.widgets[fromSection] = sourceArray + var sourceArray = Settings.data.bar.widgets[fromSection].slice(); + sourceArray.splice(index, 1); + Settings.data.bar.widgets[fromSection] = sourceArray; // Add to target section - var targetArray = Settings.data.bar.widgets[toSection].slice() - targetArray.push(widget) - Settings.data.bar.widgets[toSection] = targetArray + var targetArray = Settings.data.bar.widgets[toSection].slice(); + targetArray.push(widget); + Settings.data.bar.widgets[toSection] = targetArray; //Logger.i("BarTab", `Moved widget ${widget.id} from ${fromSection} to ${toSection}`) } @@ -373,33 +383,33 @@ ColumnLayout { // Data model functions function getWidgetLocations(widgetId) { if (!BarService) - return [] - const instances = BarService.getAllRegisteredWidgets() - const locations = {} + return []; + const instances = BarService.getAllRegisteredWidgets(); + const locations = {}; for (var i = 0; i < instances.length; i++) { if (instances[i].widgetId === widgetId) { - const section = instances[i].section + const section = instances[i].section; if (section === "left") - locations["L"] = true + locations["L"] = true; else if (section === "center") - locations["C"] = true + locations["C"] = true; else if (section === "right") - locations["R"] = true + locations["R"] = true; } } - return Object.keys(locations).join('') + return Object.keys(locations).join(''); } function updateAvailableWidgetsModel() { - availableWidgets.clear() - const widgets = BarWidgetRegistry.getAvailableWidgets() + availableWidgets.clear(); + const widgets = BarWidgetRegistry.getAvailableWidgets(); widgets.forEach(entry => { availableWidgets.append({ "key": entry, "name": entry, "badgeLocations": getWidgetLocations(entry) - }) - }) + }); + }); } // Base list model for all combo boxes @@ -408,13 +418,13 @@ ColumnLayout { } Component.onCompleted: { - updateAvailableWidgetsModel() + updateAvailableWidgetsModel(); } Connections { target: BarService function onActiveWidgetsChanged() { - updateAvailableWidgetsModel() + updateAvailableWidgetsModel(); } } } diff --git a/Modules/Panels/Settings/Tabs/ColorSchemeTab.qml b/Modules/Panels/Settings/Tabs/ColorSchemeTab.qml index 58b2d797..815151a4 100644 --- a/Modules/Panels/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Panels/Settings/Tabs/ColorSchemeTab.qml @@ -4,8 +4,8 @@ import QtQuick.Layouts import Quickshell import Quickshell.Io import qs.Commons -import qs.Services.Theming import qs.Services.System +import qs.Services.Theming import qs.Services.UI import qs.Widgets @@ -23,13 +23,13 @@ ColumnLayout { Component.onCompleted: { for (var h = 0; h < 24; h++) { for (var m = 0; m < 60; m += 30) { - var hh = ("0" + h).slice(-2) - var mm = ("0" + m).slice(-2) - var key = hh + ":" + mm + var hh = ("0" + h).slice(-2); + var mm = ("0" + m).slice(-2); + var key = hh + ":" + mm; timeOptions.append({ "key": key, "name": key - }) + }); } } } @@ -38,68 +38,68 @@ ColumnLayout { // Helper function to extract scheme name from path function extractSchemeName(schemePath) { - var pathParts = schemePath.split("/") - var filename = pathParts[pathParts.length - 1] - var schemeName = filename.replace(".json", "") + var pathParts = schemePath.split("/"); + var filename = pathParts[pathParts.length - 1]; + var schemeName = filename.replace(".json", ""); if (schemeName === "Noctalia-default") { - schemeName = "Noctalia (default)" + schemeName = "Noctalia (default)"; } else if (schemeName === "Noctalia-legacy") { - schemeName = "Noctalia (legacy)" + schemeName = "Noctalia (legacy)"; } else if (schemeName === "Tokyo-Night") { - schemeName = "Tokyo Night" + schemeName = "Tokyo Night"; } - return schemeName + return schemeName; } // Helper function to get color from scheme file (supports dark/light variants) function getSchemeColor(schemeName, colorKey) { // Access cache version to create dependency - var _ = cacheVersion + var _ = cacheVersion; if (schemeColorsCache[schemeName]) { - var entry = schemeColorsCache[schemeName] - var variant = entry + var entry = schemeColorsCache[schemeName]; + var variant = entry; // Check if scheme has dark/light variants if (entry.dark || entry.light) { - variant = Settings.data.colorSchemes.darkMode ? (entry.dark || entry.light) : (entry.light || entry.dark) + variant = Settings.data.colorSchemes.darkMode ? (entry.dark || entry.light) : (entry.light || entry.dark); } if (variant && variant[colorKey]) { - return variant[colorKey] + return variant[colorKey]; } } // Return visible defaults while loading if (colorKey === "mSurface") - return Color.mSurfaceVariant + return Color.mSurfaceVariant; if (colorKey === "mPrimary") - return Color.mPrimary + return Color.mPrimary; if (colorKey === "mSecondary") - return Color.mSecondary + return Color.mSecondary; if (colorKey === "mTertiary") - return Color.mTertiary + return Color.mTertiary; if (colorKey === "mError") - return Color.mError - return Color.mOnSurfaceVariant + return Color.mError; + return Color.mOnSurfaceVariant; } // This function is called by the FileView Repeater when a scheme file is loaded function schemeLoaded(schemeName, jsonData) { - var value = jsonData || {} - schemeColorsCache[schemeName] = value + var value = jsonData || {}; + schemeColorsCache[schemeName] = value; // Force UI update by incrementing cache version - cacheVersion++ + cacheVersion++; } // When the list of available schemes changes, clear the cache Connections { target: ColorSchemeService function onSchemesChanged() { - schemeColorsCache = {} - cacheVersion++ + schemeColorsCache = {}; + cacheVersion++; } } @@ -111,11 +111,11 @@ ColumnLayout { onExited: function (exitCode) { if (exitCode === 0) { - Settings.data.colorSchemes.useWallpaperColors = true - AppThemeService.generate() - ToastService.showNotice(I18n.tr("toast.wallpaper-colors.label"), I18n.tr("toast.wallpaper-colors.enabled"), "settings-color-scheme") + Settings.data.colorSchemes.useWallpaperColors = true; + AppThemeService.generate(); + ToastService.showNotice(I18n.tr("toast.wallpaper-colors.label"), I18n.tr("toast.wallpaper-colors.enabled"), "settings-color-scheme"); } else { - ToastService.showWarning(I18n.tr("oast.wallpaper-colors.label"), I18n.tr("toast.wallpaper-colors.not-installed")) + ToastService.showWarning(I18n.tr("oast.wallpaper-colors.label"), I18n.tr("toast.wallpaper-colors.not-installed")); } } @@ -125,8 +125,8 @@ ColumnLayout { // A non-visual Item to host the Repeater that loads the color scheme files Item { - visible: false id: fileLoaders + visible: false Repeater { model: ColorSchemeService.schemes @@ -135,14 +135,14 @@ ColumnLayout { path: modelData blockLoading: false onLoaded: { - var schemeName = root.extractSchemeName(path) + var schemeName = root.extractSchemeName(path); try { - var jsonData = JSON.parse(text()) - root.schemeLoaded(schemeName, jsonData) + var jsonData = JSON.parse(text()); + root.schemeLoaded(schemeName, jsonData); } catch (e) { - Logger.w("ColorSchemeTab", "Failed to parse JSON for scheme:", schemeName, e) - root.schemeLoaded(schemeName, null) + Logger.w("ColorSchemeTab", "Failed to parse JSON for scheme:", schemeName, e); + root.schemeLoaded(schemeName, null); } } } @@ -162,8 +162,8 @@ ColumnLayout { description: I18n.tr("settings.color-scheme.dark-mode.switch.description") checked: Settings.data.colorSchemes.darkMode onToggled: checked => { - Settings.data.colorSchemes.darkMode = checked - root.cacheVersion++ // Force UI update for dark/light variants + Settings.data.colorSchemes.darkMode = checked; + root.cacheVersion++; // Force UI update for dark/light variants } } @@ -171,22 +171,26 @@ ColumnLayout { label: I18n.tr("settings.color-scheme.dark-mode.mode.label") description: I18n.tr("settings.color-scheme.dark-mode.mode.description") - model: [{ + model: [ + { "name": I18n.tr("settings.color-scheme.dark-mode.mode.off"), "key": "off" - }, { + }, + { "name": I18n.tr("settings.color-scheme.dark-mode.mode.manual"), "key": "manual" - }, { + }, + { "name": I18n.tr("settings.color-scheme.dark-mode.mode.location"), "key": "location" - }] + } + ] currentKey: Settings.data.colorSchemes.schedulingMode onSelected: key => { - Settings.data.colorSchemes.schedulingMode = key - AppThemeService.generate() + Settings.data.colorSchemes.schedulingMode = key; + AppThemeService.generate(); } } @@ -246,13 +250,13 @@ ColumnLayout { checked: Settings.data.colorSchemes.useWallpaperColors onToggled: checked => { if (checked) { - matugenCheck.running = true + matugenCheck.running = true; } else { - Settings.data.colorSchemes.useWallpaperColors = false - ToastService.showNotice(I18n.tr("toast.wallpaper-colors.label"), I18n.tr("toast.wallpaper-colors.disabled"), "settings-color-scheme") + Settings.data.colorSchemes.useWallpaperColors = false; + ToastService.showNotice(I18n.tr("toast.wallpaper-colors.label"), I18n.tr("toast.wallpaper-colors.disabled"), "settings-color-scheme"); if (Settings.data.colorSchemes.predefinedScheme) { - ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme); } } } @@ -266,37 +270,46 @@ ColumnLayout { opacity: Settings.data.colorSchemes.useWallpaperColors ? 1.0 : 0.6 visible: Settings.data.colorSchemes.useWallpaperColors - model: [{ + model: [ + { "key": "scheme-content", "name": "Content" - }, { + }, + { "key": "scheme-expressive", "name": "Expressive" - }, { + }, + { "key": "scheme-fidelity", "name": "Fidelity" - }, { + }, + { "key": "scheme-fruit-salad", "name": "Fruit Salad" - }, { + }, + { "key": "scheme-monochrome", "name": "Monochrome" - }, { + }, + { "key": "scheme-neutral", "name": "Neutral" - }, { + }, + { "key": "scheme-rainbow", "name": "Rainbow" - }, { + }, + { "key": "scheme-tonal-spot", "name": "Tonal Spot" - }] + } + ] currentKey: Settings.data.colorSchemes.matugenSchemeType onSelected: key => { - Settings.data.colorSchemes.matugenSchemeType = key - AppThemeService.generate() + Settings.data.colorSchemes.matugenSchemeType = key; + AppThemeService.generate(); } } @@ -342,12 +355,12 @@ ColumnLayout { border.width: Style.borderL border.color: { if (Settings.data.colorSchemes.predefinedScheme === schemeName) { - return Color.mSecondary + return Color.mSecondary; } if (itemMouseArea.containsMouse) { - return Color.mHover + return Color.mHover; } - return Color.mOutline + return Color.mOutline; } RowLayout { @@ -404,11 +417,11 @@ ColumnLayout { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { - Settings.data.colorSchemes.useWallpaperColors = false - Logger.i("ColorSchemeTab", "Disabled wallpaper colors") + Settings.data.colorSchemes.useWallpaperColors = false; + Logger.i("ColorSchemeTab", "Disabled wallpaper colors"); - Settings.data.colorSchemes.predefinedScheme = schemeItem.schemeName - ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + Settings.data.colorSchemes.predefinedScheme = schemeItem.schemeName; + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme); } } @@ -450,9 +463,9 @@ ColumnLayout { description: I18n.tr("settings.color-scheme.predefined.generate-templates.description") checked: Settings.data.colorSchemes.generateTemplatesForPredefined onToggled: checked => { - Settings.data.colorSchemes.generateTemplatesForPredefined = checked + Settings.data.colorSchemes.generateTemplatesForPredefined = checked; if (!Settings.data.colorSchemes.useWallpaperColors && Settings.data.colorSchemes.predefinedScheme) { - ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme); } } Layout.topMargin: Style.marginL @@ -490,8 +503,8 @@ ColumnLayout { }) checked: Settings.data.templates.gtk onToggled: checked => { - Settings.data.templates.gtk = checked - AppThemeService.generate() + Settings.data.templates.gtk = checked; + AppThemeService.generate(); } } @@ -502,8 +515,8 @@ ColumnLayout { }) checked: Settings.data.templates.qt onToggled: checked => { - Settings.data.templates.qt = checked - AppThemeService.generate() + Settings.data.templates.qt = checked; + AppThemeService.generate(); } } @@ -514,8 +527,8 @@ ColumnLayout { }) checked: Settings.data.templates.kcolorscheme onToggled: checked => { - Settings.data.templates.kcolorscheme = checked - AppThemeService.generate() + Settings.data.templates.kcolorscheme = checked; + AppThemeService.generate(); } } } @@ -539,8 +552,8 @@ ColumnLayout { opacity: ProgramCheckerService.alacrittyAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.alacrittyAvailable) { - Settings.data.templates.alacritty = checked - AppThemeService.generate() + Settings.data.templates.alacritty = checked; + AppThemeService.generate(); } } } @@ -557,8 +570,8 @@ ColumnLayout { opacity: ProgramCheckerService.kittyAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.kittyAvailable) { - Settings.data.templates.kitty = checked - AppThemeService.generate() + Settings.data.templates.kitty = checked; + AppThemeService.generate(); } } } @@ -575,8 +588,8 @@ ColumnLayout { opacity: ProgramCheckerService.ghosttyAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.ghosttyAvailable) { - Settings.data.templates.ghostty = checked - AppThemeService.generate() + Settings.data.templates.ghostty = checked; + AppThemeService.generate(); } } } @@ -593,8 +606,8 @@ ColumnLayout { opacity: ProgramCheckerService.footAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.footAvailable) { - Settings.data.templates.foot = checked - AppThemeService.generate() + Settings.data.templates.foot = checked; + AppThemeService.generate(); } } } @@ -611,8 +624,8 @@ ColumnLayout { opacity: ProgramCheckerService.weztermAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.weztermAvailable) { - Settings.data.templates.wezterm = checked - AppThemeService.generate() + Settings.data.templates.wezterm = checked; + AppThemeService.generate(); } } } @@ -637,8 +650,8 @@ ColumnLayout { opacity: ProgramCheckerService.fuzzelAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.fuzzelAvailable) { - Settings.data.templates.fuzzel = checked - AppThemeService.generate() + Settings.data.templates.fuzzel = checked; + AppThemeService.generate(); } } } @@ -649,15 +662,15 @@ ColumnLayout { label: "Discord" description: { if (ProgramCheckerService.availableDiscordClients.length === 0) { - return I18n.tr("settings.color-scheme.templates.programs.discord.description-missing") + return I18n.tr("settings.color-scheme.templates.programs.discord.description-missing"); } else { // Show detected clients - var clientInfo = [] + var clientInfo = []; for (var i = 0; i < ProgramCheckerService.availableDiscordClients.length; i++) { - var client = ProgramCheckerService.availableDiscordClients[i] - clientInfo.push(client.name.charAt(0).toUpperCase() + client.name.slice(1)) + var client = ProgramCheckerService.availableDiscordClients[i]; + clientInfo.push(client.name.charAt(0).toUpperCase() + client.name.slice(1)); } - return "Detected: " + clientInfo.join(", ") + return "Detected: " + clientInfo.join(", "); } } Layout.fillWidth: true @@ -667,9 +680,9 @@ ColumnLayout { opacity: ProgramCheckerService.availableDiscordClients.length > 0 ? 1.0 : 0.6 onToggled: checked => { // Set unified discord property - Settings.data.templates.discord = checked + Settings.data.templates.discord = checked; if (ProgramCheckerService.availableDiscordClients.length > 0) { - AppThemeService.generate() + AppThemeService.generate(); } } } @@ -686,8 +699,8 @@ ColumnLayout { opacity: ProgramCheckerService.pywalfoxAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.pywalfoxAvailable) { - Settings.data.templates.pywalfox = checked - AppThemeService.generate() + Settings.data.templates.pywalfox = checked; + AppThemeService.generate(); } } } @@ -703,8 +716,8 @@ ColumnLayout { opacity: ProgramCheckerService.vicinaeAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.vicinaeAvailable) { - Settings.data.templates.vicinae = checked - AppThemeService.generate() + Settings.data.templates.vicinae = checked; + AppThemeService.generate(); } } } @@ -720,8 +733,8 @@ ColumnLayout { opacity: ProgramCheckerService.walkerAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.walkerAvailable) { - Settings.data.templates.walker = checked - AppThemeService.generate() + Settings.data.templates.walker = checked; + AppThemeService.generate(); } } } @@ -732,17 +745,17 @@ ColumnLayout { label: "Code" description: { if (ProgramCheckerService.availableCodeClients.length === 0) { - return I18n.tr("settings.color-scheme.templates.programs.code.description-missing") + return I18n.tr("settings.color-scheme.templates.programs.code.description-missing"); } else { // Show detected clients - var clientInfo = [] + var clientInfo = []; for (var i = 0; i < ProgramCheckerService.availableCodeClients.length; i++) { - var client = ProgramCheckerService.availableCodeClients[i] + var client = ProgramCheckerService.availableCodeClients[i]; // Capitalize first letter and format nicely - var clientName = client.name === "code" ? "VSCode" : "VSCodium" - clientInfo.push(clientName) + var clientName = client.name === "code" ? "VSCode" : "VSCodium"; + clientInfo.push(clientName); } - return "Detected: " + clientInfo.join(", ") + return "Detected: " + clientInfo.join(", "); } } Layout.fillWidth: true @@ -752,9 +765,9 @@ ColumnLayout { opacity: ProgramCheckerService.availableCodeClients.length > 0 ? 1.0 : 0.6 onToggled: checked => { // Set unified code property - Settings.data.templates.code = checked + Settings.data.templates.code = checked; if (ProgramCheckerService.availableCodeClients.length > 0) { - AppThemeService.generate() + AppThemeService.generate(); } } } @@ -771,8 +784,8 @@ ColumnLayout { opacity: ProgramCheckerService.spicetifyAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.spicetifyAvailable) { - Settings.data.templates.spicetify = checked - AppThemeService.generate() + Settings.data.templates.spicetify = checked; + AppThemeService.generate(); } } } @@ -789,11 +802,11 @@ ColumnLayout { description: I18n.tr("settings.color-scheme.templates.misc.user-templates.description") checked: Settings.data.templates.enableUserTemplates onToggled: checked => { - Settings.data.templates.enableUserTemplates = checked + Settings.data.templates.enableUserTemplates = checked; if (checked) { - TemplateRegistry.writeUserTemplatesToml() + TemplateRegistry.writeUserTemplatesToml(); } - AppThemeService.generate() + AppThemeService.generate(); } } } diff --git a/Modules/Panels/Settings/Tabs/ControlCenterTab.qml b/Modules/Panels/Settings/Tabs/ControlCenterTab.qml index 6cdfc69b..e9b26674 100644 --- a/Modules/Panels/Settings/Tabs/ControlCenterTab.qml +++ b/Modules/Panels/Settings/Tabs/ControlCenterTab.qml @@ -11,95 +11,101 @@ ColumnLayout { spacing: Style.marginL property list cardsModel: [] - property list cardsDefault: [{ + property list cardsDefault: [ + { "id": "profile-card", "text": "Profile", "enabled": true, "required": true - }, { + }, + { "id": "shortcuts-card", "text": "Shortcuts", "enabled": true, "required": false - }, { + }, + { "id": "audio-card", "text": "Audio Sliders", "enabled": true, "required": false - }, { + }, + { "id": "weather-card", "text": "Weather", "enabled": true, "required": false - }, { + }, + { "id": "media-sysmon-card", "text": "Media and System Monitor", "enabled": true, "required": false - }] + } + ] function saveCards() { - var toSave = [] + var toSave = []; for (var i = 0; i < cardsModel.length; i++) { toSave.push({ "id": cardsModel[i].id, "enabled": cardsModel[i].enabled - }) + }); } - Settings.data.controlCenter.cards = toSave + Settings.data.controlCenter.cards = toSave; } Component.onCompleted: { // Fill out availableWidgets ListModel - availableWidgets.clear() - var sortedEntries = ControlCenterWidgetRegistry.getAvailableWidgets().slice().sort() + availableWidgets.clear(); + var sortedEntries = ControlCenterWidgetRegistry.getAvailableWidgets().slice().sort(); sortedEntries.forEach(entry => { availableWidgets.append({ "key": entry, "name": entry - }) - }) + }); + }); // Starts empty - cardsModel = [] + cardsModel = []; // Add the cards available in settings for (var i = 0; i < Settings.data.controlCenter.cards.length; i++) { - const settingCard = Settings.data.controlCenter.cards[i] + const settingCard = Settings.data.controlCenter.cards[i]; for (var j = 0; j < cardsDefault.length; j++) { if (settingCard.id === cardsDefault[j].id) { - var card = cardsDefault[j] - card.enabled = settingCard.enabled + var card = cardsDefault[j]; + card.enabled = settingCard.enabled; // Auto-disable weather card if weather is disabled if (card.id === "weather-card" && !Settings.data.location.weatherEnabled) { - card.enabled = false + card.enabled = false; } - cardsModel.push(card) + cardsModel.push(card); } } } // Add any missing cards from default for (var i = 0; i < cardsDefault.length; i++) { - var found = false + var found = false; for (var j = 0; j < cardsModel.length; j++) { if (cardsModel[j].id === cardsDefault[i].id) { - found = true - break + found = true; + break; } } if (!found) { - var card = cardsDefault[i] + var card = cardsDefault[i]; // Auto-disable weather card if weather is disabled if (card.id === "weather-card" && !Settings.data.location.weatherEnabled) { - card.enabled = false + card.enabled = false; } - cardsModel.push(card) + cardsModel.push(card); } } - saveCards() + saveCards(); } ColumnLayout { @@ -116,34 +122,43 @@ ColumnLayout { label: I18n.tr("settings.control-center.position.label") description: I18n.tr("settings.control-center.position.description") Layout.fillWidth: true - model: [{ + model: [ + { "key": "close_to_bar_button", "name": I18n.tr("options.control-center.position.close_to_bar_button") - }, { + }, + { "key": "center", "name": I18n.tr("options.control-center.position.center") - }, { + }, + { "key": "top_center", "name": I18n.tr("options.control-center.position.top_center") - }, { + }, + { "key": "top_left", "name": I18n.tr("options.control-center.position.top_left") - }, { + }, + { "key": "top_right", "name": I18n.tr("options.control-center.position.top_right") - }, { + }, + { "key": "bottom_center", "name": I18n.tr("options.control-center.position.bottom_center") - }, { + }, + { "key": "bottom_left", "name": I18n.tr("options.control-center.position.bottom_left") - }, { + }, + { "key": "bottom_right", "name": I18n.tr("options.control-center.position.bottom_right") - }] + } + ] currentKey: Settings.data.controlCenter.position onSelected: function (key) { - Settings.data.controlCenter.position = key + Settings.data.controlCenter.position = key; } } } @@ -168,15 +183,15 @@ ColumnLayout { target: Settings.data.location function onWeatherEnabledChanged() { // Auto-disable weather card when weather is disabled - var newModel = cardsModel.slice() + var newModel = cardsModel.slice(); for (var i = 0; i < newModel.length; i++) { if (newModel[i].id === "weather-card") { newModel[i] = Object.assign({}, newModel[i], { "enabled": Settings.data.location.weatherEnabled - }) - cardsModel = newModel - saveCards() - break + }); + cardsModel = newModel; + saveCards(); + break; } } } @@ -188,20 +203,20 @@ ColumnLayout { disabledIds: Settings.data.location.weatherEnabled ? [] : ["weather-card"] onItemToggled: function (index, enabled) { //Logger.i("ControlCenterTab", "Item", index, "toggled to", enabled) - var newModel = cardsModel.slice() + var newModel = cardsModel.slice(); newModel[index] = Object.assign({}, newModel[index], { "enabled": enabled - }) - cardsModel = newModel - saveCards() + }); + cardsModel = newModel; + saveCards(); } onItemsReordered: function (fromIndex, toIndex) { //Logger.i("ControlCenterTab", "Item moved from", fromIndex, "to", toIndex) - var newModel = cardsModel.slice() - var item = newModel.splice(fromIndex, 1)[0] - newModel.splice(toIndex, 0, item) - cardsModel = newModel - saveCards() + var newModel = cardsModel.slice(); + var item = newModel.splice(fromIndex, 1)[0]; + newModel.splice(toIndex, 0, item); + cardsModel = newModel; + saveCards(); } } } @@ -277,25 +292,25 @@ ColumnLayout { function _addWidgetToSection(widgetId, section) { var newWidget = { "id": widgetId - } + }; if (ControlCenterWidgetRegistry.widgetHasUserSettings(widgetId)) { - var metadata = ControlCenterWidgetRegistry.widgetMetadata[widgetId] + var metadata = ControlCenterWidgetRegistry.widgetMetadata[widgetId]; if (metadata) { Object.keys(metadata).forEach(function (key) { if (key !== "allowUserSettings") { - newWidget[key] = metadata[key] + newWidget[key] = metadata[key]; } - }) + }); } } - Settings.data.controlCenter.shortcuts[section].push(newWidget) + Settings.data.controlCenter.shortcuts[section].push(newWidget); } function _removeWidgetFromSection(section, index) { if (index >= 0 && index < Settings.data.controlCenter.shortcuts[section].length) { - var newArray = Settings.data.controlCenter.shortcuts[section].slice() - var removedWidgets = newArray.splice(index, 1) - Settings.data.controlCenter.shortcuts[section] = newArray + var newArray = Settings.data.controlCenter.shortcuts[section].slice(); + var removedWidgets = newArray.splice(index, 1); + Settings.data.controlCenter.shortcuts[section] = newArray; } } @@ -303,29 +318,29 @@ ColumnLayout { if (fromIndex >= 0 && fromIndex < Settings.data.controlCenter.shortcuts[section].length && toIndex >= 0 && toIndex < Settings.data.controlCenter.shortcuts[section].length) { // Create a new array to avoid modifying the original - var newArray = Settings.data.controlCenter.shortcuts[section].slice() - var item = newArray[fromIndex] - newArray.splice(fromIndex, 1) - newArray.splice(toIndex, 0, item) + var newArray = Settings.data.controlCenter.shortcuts[section].slice(); + var item = newArray[fromIndex]; + newArray.splice(fromIndex, 1); + newArray.splice(toIndex, 0, item); - Settings.data.controlCenter.shortcuts[section] = newArray + Settings.data.controlCenter.shortcuts[section] = newArray; } } function _moveWidgetBetweenSections(fromSection, index, toSection) { // Get the widget from the source section if (index >= 0 && index < Settings.data.controlCenter.shortcuts[fromSection].length) { - var widget = Settings.data.controlCenter.shortcuts[fromSection][index] + var widget = Settings.data.controlCenter.shortcuts[fromSection][index]; // Remove from source section - var sourceArray = Settings.data.controlCenter.shortcuts[fromSection].slice() - sourceArray.splice(index, 1) - Settings.data.controlCenter.shortcuts[fromSection] = sourceArray + var sourceArray = Settings.data.controlCenter.shortcuts[fromSection].slice(); + sourceArray.splice(index, 1); + Settings.data.controlCenter.shortcuts[fromSection] = sourceArray; // Add to target section - var targetArray = Settings.data.controlCenter.shortcuts[toSection].slice() - targetArray.push(widget) - Settings.data.controlCenter.shortcuts[toSection] = targetArray + var targetArray = Settings.data.controlCenter.shortcuts[toSection].slice(); + targetArray.push(widget); + Settings.data.controlCenter.shortcuts[toSection] = targetArray; //Logger.i("BarTab", `Moved widget ${widget.id} from ${fromSection} to ${toSection}`) } @@ -334,10 +349,10 @@ ColumnLayout { function _updateWidgetSettingsInSection(section, index, settings) { // Create a new array to trigger QML's change detection for persistence. // This is crucial for Settings.data to detect the change and persist it. - var newSectionArray = Settings.data.controlCenter.shortcuts[section].slice() - newSectionArray[index] = settings - Settings.data.controlCenter.shortcuts[section] = newSectionArray - Settings.saveImmediate() + var newSectionArray = Settings.data.controlCenter.shortcuts[section].slice(); + newSectionArray[index] = settings; + Settings.data.controlCenter.shortcuts[section] = newSectionArray; + Settings.saveImmediate(); } // Base list model for all combo boxes diff --git a/Modules/Panels/Settings/Tabs/DisplayTab.qml b/Modules/Panels/Settings/Tabs/DisplayTab.qml index d9530e28..eac33485 100644 --- a/Modules/Panels/Settings/Tabs/DisplayTab.qml +++ b/Modules/Panels/Settings/Tabs/DisplayTab.qml @@ -1,12 +1,12 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Io import qs.Commons import qs.Services.Compositor -import qs.Services.Location import qs.Services.Hardware +import qs.Services.Location import qs.Widgets ColumnLayout { @@ -19,13 +19,13 @@ ColumnLayout { Component.onCompleted: { for (var h = 0; h < 24; h++) { for (var m = 0; m < 60; m += 30) { - var hh = ("0" + h).slice(-2) - var mm = ("0" + m).slice(-2) - var key = hh + ":" + mm + var hh = ("0" + h).slice(-2); + var mm = ("0" + m).slice(-2); + var key = hh + ":" + mm; timeOptions.append({ "key": key, "name": key - }) + }); } } } @@ -38,12 +38,12 @@ ColumnLayout { onExited: function (exitCode) { if (exitCode === 0) { - Settings.data.nightLight.enabled = true - NightLightService.apply() - ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.enabled"), "nightlight-on") + Settings.data.nightLight.enabled = true; + NightLightService.apply(); + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.enabled"), "nightlight-on"); } else { - Settings.data.nightLight.enabled = false - ToastService.showWarning(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.not-installed")) + Settings.data.nightLight.enabled = false; + ToastService.showWarning(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.not-installed")); } } @@ -83,13 +83,13 @@ ColumnLayout { NLabel { label: modelData.name || "Unknown" description: { - const compositorScale = CompositorService.getDisplayScale(modelData.name) + const compositorScale = CompositorService.getDisplayScale(modelData.name); I18n.tr("system.monitor-description", { "model": modelData.model, "width": modelData.width * compositorScale, "height": modelData.height * compositorScale, "scale": compositorScale - }) + }); } } @@ -118,12 +118,12 @@ ColumnLayout { enabled: brightnessMonitor ? brightnessMonitor.brightnessControlAvailable : false onMoved: value => { if (brightnessMonitor && brightnessMonitor.brightnessControlAvailable) { - brightnessMonitor.setBrightness(value) + brightnessMonitor.setBrightness(value); } } onPressedChanged: (pressed, value) => { if (brightnessMonitor && brightnessMonitor.brightnessControlAvailable) { - brightnessMonitor.setBrightness(value) + brightnessMonitor.setBrightness(value); } } Layout.fillWidth: true @@ -189,7 +189,7 @@ ColumnLayout { description: I18n.tr("settings.display.monitors.external-brightness.description") checked: Settings.data.brightness.enableDdcSupport onToggled: checked => { - Settings.data.brightness.enableDdcSupport = checked + Settings.data.brightness.enableDdcSupport = checked; // DDC detection will run on next monitor change when enabled // Monitors will stop using DDC immediately when disabled } @@ -220,12 +220,12 @@ ColumnLayout { onToggled: checked => { if (checked) { // Verify wlsunset exists before enabling - wlsunsetCheck.running = true + wlsunsetCheck.running = true; } else { - Settings.data.nightLight.enabled = false - Settings.data.nightLight.forced = false - NightLightService.apply() - ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.disabled"), "nightlight-off") + Settings.data.nightLight.enabled = false; + Settings.data.nightLight.forced = false; + NightLightService.apply(); + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.disabled"), "nightlight-off"); } } } @@ -259,12 +259,12 @@ ColumnLayout { inputMethodHints: Qt.ImhDigitsOnly Layout.alignment: Qt.AlignVCenter onEditingFinished: { - var nightTemp = parseInt(text) - var dayTemp = parseInt(Settings.data.nightLight.dayTemp) + var nightTemp = parseInt(text); + var dayTemp = parseInt(Settings.data.nightLight.dayTemp); if (!isNaN(nightTemp) && !isNaN(dayTemp)) { // Clamp value between [1000 .. (dayTemp-500)] - var clampedValue = Math.min(dayTemp - 500, Math.max(1000, nightTemp)) - text = Settings.data.nightLight.nightTemp = clampedValue.toString() + var clampedValue = Math.min(dayTemp - 500, Math.max(1000, nightTemp)); + text = Settings.data.nightLight.nightTemp = clampedValue.toString(); } } } @@ -280,12 +280,12 @@ ColumnLayout { inputMethodHints: Qt.ImhDigitsOnly Layout.alignment: Qt.AlignVCenter onEditingFinished: { - var dayTemp = parseInt(text) - var nightTemp = parseInt(Settings.data.nightLight.nightTemp) + var dayTemp = parseInt(text); + var nightTemp = parseInt(Settings.data.nightLight.nightTemp); if (!isNaN(nightTemp) && !isNaN(dayTemp)) { // Clamp value between [(nightTemp+500) .. 6500] - var clampedValue = Math.max(nightTemp + 500, Math.min(6500, dayTemp)) - text = Settings.data.nightLight.dayTemp = clampedValue.toString() + var clampedValue = Math.max(nightTemp + 500, Math.min(6500, dayTemp)); + text = Settings.data.nightLight.dayTemp = clampedValue.toString(); } } } @@ -356,12 +356,12 @@ ColumnLayout { description: I18n.tr("settings.display.night-light.force-activation.description") checked: Settings.data.nightLight.forced onToggled: checked => { - Settings.data.nightLight.forced = checked + Settings.data.nightLight.forced = checked; if (checked && !Settings.data.nightLight.enabled) { // Ensure enabled when forcing - wlsunsetCheck.running = true + wlsunsetCheck.running = true; } else { - NightLightService.apply() + NightLightService.apply(); } } visible: Settings.data.nightLight.enabled diff --git a/Modules/Panels/Settings/Tabs/DockTab.qml b/Modules/Panels/Settings/Tabs/DockTab.qml index 8afe2e59..5ca75804 100644 --- a/Modules/Panels/Settings/Tabs/DockTab.qml +++ b/Modules/Panels/Settings/Tabs/DockTab.qml @@ -13,15 +13,15 @@ ColumnLayout { // Helper functions to update arrays immutably function addMonitor(list, name) { - const arr = (list || []).slice() + const arr = (list || []).slice(); if (!arr.includes(name)) - arr.push(name) - return arr + arr.push(name); + return arr; } function removeMonitor(list, name) { return (list || []).filter(function (n) { - return n !== name - }) + return n !== name; + }); } NHeader { @@ -42,19 +42,23 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.dock.appearance.display.label") description: I18n.tr("settings.dock.appearance.display.description") - model: [{ + model: [ + { "key": "always_visible", "name": I18n.tr("settings.dock.appearance.display.always-visible") - }, { + }, + { "key": "auto_hide", "name": I18n.tr("settings.dock.appearance.display.auto-hide") - }, { + }, + { "key": "exclusive", "name": I18n.tr("settings.dock.appearance.display.exclusive") - }] + } + ] currentKey: Settings.data.dock.displayMode onSelected: key => { - Settings.data.dock.displayMode = key + Settings.data.dock.displayMode = key; } } @@ -158,20 +162,20 @@ ColumnLayout { Layout.fillWidth: true label: modelData.name || "Unknown" description: { - const compositorScale = CompositorService.getDisplayScale(modelData.name) + const compositorScale = CompositorService.getDisplayScale(modelData.name); I18n.tr("system.monitor-description", { "model": modelData.model, "width": modelData.width * compositorScale, "height": modelData.height * compositorScale, "scale": compositorScale - }) + }); } checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { - Settings.data.dock.monitors = addMonitor(Settings.data.dock.monitors, modelData.name) + Settings.data.dock.monitors = addMonitor(Settings.data.dock.monitors, modelData.name); } else { - Settings.data.dock.monitors = removeMonitor(Settings.data.dock.monitors, modelData.name) + Settings.data.dock.monitors = removeMonitor(Settings.data.dock.monitors, modelData.name); } } } diff --git a/Modules/Panels/Settings/Tabs/GeneralTab.qml b/Modules/Panels/Settings/Tabs/GeneralTab.qml index 4e7e5732..481f4013 100644 --- a/Modules/Panels/Settings/Tabs/GeneralTab.qml +++ b/Modules/Panels/Settings/Tabs/GeneralTab.qml @@ -42,7 +42,7 @@ ColumnLayout { buttonTooltip: "Browse for avatar image" onInputEditingFinished: Settings.data.general.avatarImage = text onButtonClicked: { - avatarPicker.openFilePicker() + avatarPicker.openFilePicker(); } } } @@ -55,7 +55,7 @@ ColumnLayout { nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.gif", "*.pnm", "*.bmp"] onAccepted: paths => { if (paths.length > 0) { - Settings.data.general.avatarImage = paths[0] + Settings.data.general.avatarImage = paths[0]; } } } @@ -91,7 +91,7 @@ ColumnLayout { popupHeight: 420 minimumWidth: 300 onSelected: function (key) { - Settings.data.ui.fontDefault = key + Settings.data.ui.fontDefault = key; } } @@ -105,7 +105,7 @@ ColumnLayout { popupHeight: 320 minimumWidth: 300 onSelected: function (key) { - Settings.data.ui.fontFixed = key + Settings.data.ui.fontFixed = key; } } @@ -205,22 +205,24 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.general.language.select.label") description: I18n.tr("settings.general.language.select.description") - model: [{ + model: [ + { "key": "", "name": I18n.tr("settings.general.language.select.auto-detect") + " (" + I18n.systemDetectedLangCode + ")" - }].concat(I18n.availableLanguages.map(function (langCode) { - return { - "key": langCode, - "name": langCode - } - })) + } + ].concat(I18n.availableLanguages.map(function (langCode) { + return { + "key": langCode, + "name": langCode + }; + })) currentKey: Settings.data.general.language onSelected: key => { - Settings.data.general.language = key + Settings.data.general.language = key; if (key === "") { - I18n.detectLanguage() // Re-detect system language if "Automatic" is selected + I18n.detectLanguage(); // Re-detect system language if "Automatic" is selected } else { - I18n.setLanguage(key) // Set specific language + I18n.setLanguage(key); // Set specific language } } } @@ -236,19 +238,19 @@ ColumnLayout { visible: !HostService.isNixOS text: I18n.tr("settings.general.launch-setup-wizard") onClicked: { - var targetScreen = PanelService.openedPanel ? PanelService.openedPanel.screen : (Quickshell.screens.length > 0 ? Quickshell.screens[0] : null) + var targetScreen = PanelService.openedPanel ? PanelService.openedPanel.screen : (Quickshell.screens.length > 0 ? Quickshell.screens[0] : null); if (!targetScreen) { - return + return; } - var setupPanel = PanelService.getPanel("setupWizardPanel", targetScreen) + var setupPanel = PanelService.getPanel("setupWizardPanel", targetScreen); if (setupPanel) { - setupPanel.open() + setupPanel.open(); } else { Qt.callLater(() => { - var sp = PanelService.getPanel("setupWizardPanel", targetScreen) + var sp = PanelService.getPanel("setupWizardPanel", targetScreen); if (sp) - sp.open() - }) + sp.open(); + }); } } } diff --git a/Modules/Panels/Settings/Tabs/HooksTab.qml b/Modules/Panels/Settings/Tabs/HooksTab.qml index b129bd7c..7a17d1af 100644 --- a/Modules/Panels/Settings/Tabs/HooksTab.qml +++ b/Modules/Panels/Settings/Tabs/HooksTab.qml @@ -41,11 +41,11 @@ ColumnLayout { placeholderText: I18n.tr("settings.hooks.wallpaper-changed.placeholder") text: Settings.data.hooks.wallpaperChange onEditingFinished: { - Settings.data.hooks.wallpaperChange = wallpaperHookInput.text + Settings.data.hooks.wallpaperChange = wallpaperHookInput.text; } onActionClicked: { if (wallpaperHookInput.text) { - HooksService.executeWallpaperHook("test", "test-screen") + HooksService.executeWallpaperHook("test", "test-screen"); } } Layout.fillWidth: true @@ -63,11 +63,11 @@ ColumnLayout { placeholderText: I18n.tr("settings.hooks.theme-changed.placeholder") text: Settings.data.hooks.darkModeChange onEditingFinished: { - Settings.data.hooks.darkModeChange = darkModeHookInput.text + Settings.data.hooks.darkModeChange = darkModeHookInput.text; } onActionClicked: { if (darkModeHookInput.text) { - HooksService.executeDarkModeHook(Settings.data.colorSchemes.darkMode) + HooksService.executeDarkModeHook(Settings.data.colorSchemes.darkMode); } } Layout.fillWidth: true diff --git a/Modules/Panels/Settings/Tabs/LauncherTab.qml b/Modules/Panels/Settings/Tabs/LauncherTab.qml index a5762d17..976d4b50 100644 --- a/Modules/Panels/Settings/Tabs/LauncherTab.qml +++ b/Modules/Panels/Settings/Tabs/LauncherTab.qml @@ -18,34 +18,43 @@ ColumnLayout { label: I18n.tr("settings.launcher.settings.position.label") description: I18n.tr("settings.launcher.settings.position.description") Layout.fillWidth: true - model: [{ + model: [ + { "key": "follow_bar", "name": I18n.tr("options.launcher.position.follow_bar") - }, { + }, + { "key": "center", "name": I18n.tr("options.launcher.position.center") - }, { + }, + { "key": "top_center", "name": I18n.tr("options.launcher.position.top_center") - }, { + }, + { "key": "top_left", "name": I18n.tr("options.launcher.position.top_left") - }, { + }, + { "key": "top_right", "name": I18n.tr("options.launcher.position.top_right") - }, { + }, + { "key": "bottom_left", "name": I18n.tr("options.launcher.position.bottom_left") - }, { + }, + { "key": "bottom_right", "name": I18n.tr("options.launcher.position.bottom_right") - }, { + }, + { "key": "bottom_center", "name": I18n.tr("options.launcher.position.bottom_center") - }] + } + ] currentKey: Settings.data.appLauncher.position onSelected: function (key) { - Settings.data.appLauncher.position = key + Settings.data.appLauncher.position = key; } } @@ -71,9 +80,9 @@ ColumnLayout { opacity: ProgramCheckerService.app2unitAvailable ? 1.0 : 0.6 onToggled: checked => { if (ProgramCheckerService.app2unitAvailable) { - Settings.data.appLauncher.useApp2Unit = checked + Settings.data.appLauncher.useApp2Unit = checked; if (checked) { - Settings.data.appLauncher.customLaunchPrefixEnabled = false + Settings.data.appLauncher.customLaunchPrefixEnabled = false; } } } @@ -85,7 +94,7 @@ ColumnLayout { Layout.fillWidth: true text: Settings.data.appLauncher.terminalCommand onEditingFinished: { - Settings.data.appLauncher.terminalCommand = text + Settings.data.appLauncher.terminalCommand = text; } } @@ -95,9 +104,9 @@ ColumnLayout { checked: Settings.data.appLauncher.customLaunchPrefixEnabled enabled: !Settings.data.appLauncher.useApp2Unit onToggled: checked => { - Settings.data.appLauncher.customLaunchPrefixEnabled = checked + Settings.data.appLauncher.customLaunchPrefixEnabled = checked; if (checked) { - Settings.data.appLauncher.useApp2Unit = false + Settings.data.appLauncher.useApp2Unit = false; } } } @@ -110,7 +119,7 @@ ColumnLayout { enabled: Settings.data.appLauncher.customLaunchPrefixEnabled visible: Settings.data.appLauncher.customLaunchPrefixEnabled onEditingFinished: { - Settings.data.appLauncher.customLaunchPrefix = text + Settings.data.appLauncher.customLaunchPrefix = text; } } diff --git a/Modules/Panels/Settings/Tabs/LocationTab.qml b/Modules/Panels/Settings/Tabs/LocationTab.qml index b91edeb6..78d3c7d6 100644 --- a/Modules/Panels/Settings/Tabs/LocationTab.qml +++ b/Modules/Panels/Settings/Tabs/LocationTab.qml @@ -26,15 +26,15 @@ ColumnLayout { placeholderText: I18n.tr("settings.location.location.search.placeholder") onEditingFinished: { // Verify the location has really changed to avoid extra resets - var newLocation = text.trim() + var newLocation = text.trim(); // If empty, set to default location if (newLocation === "") { - newLocation = Settings.defaultLocation - text = Settings.defaultLocation // Update the input field to show the default + newLocation = Settings.defaultLocation; + text = Settings.defaultLocation; // Update the input field to show the default } if (newLocation != Settings.data.location.name) { - Settings.data.location.name = newLocation - LocationService.resetWeather() + Settings.data.location.name = newLocation; + LocationService.resetWeather(); } } Layout.maximumWidth: 420 @@ -130,17 +130,21 @@ ColumnLayout { description: I18n.tr("settings.location.date-time.first-day-of-week.description") currentKey: Settings.data.location.firstDayOfWeek.toString() minimumWidth: 260 * Style.uiScaleRatio - model: [{ + model: [ + { "key": "-1", "name": I18n.tr("settings.location.date-time.first-day-of-week.automatic") - }, { + }, + { "key": "6", "name": I18n.locale.dayName(6, Locale.LongFormat) - }, // Saturday + } // Saturday + , { "key": "0", "name": I18n.locale.dayName(0, Locale.LongFormat) - }, // Sunday + } // Sunday + , { "key": "1", "name": I18n.locale.dayName(1, Locale.LongFormat) diff --git a/Modules/Panels/Settings/Tabs/NotificationsTab.qml b/Modules/Panels/Settings/Tabs/NotificationsTab.qml index ad393cf4..fe9009f1 100644 --- a/Modules/Panels/Settings/Tabs/NotificationsTab.qml +++ b/Modules/Panels/Settings/Tabs/NotificationsTab.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import qs.Commons import qs.Services.Compositor @@ -12,15 +12,15 @@ ColumnLayout { // Helper functions to update arrays immutably function addMonitor(list, name) { - const arr = (list || []).slice() + const arr = (list || []).slice(); if (!arr.includes(name)) - arr.push(name) - return arr + arr.push(name); + return arr; } function removeMonitor(list, name) { return (list || []).filter(function (n) { - return n !== name - }) + return n !== name; + }); } // General Notification Settings @@ -50,25 +50,32 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.notifications.settings.location.label") description: I18n.tr("settings.notifications.settings.location.description") - model: [{ + model: [ + { "key": "top", "name": I18n.tr("options.launcher.position.top_center") - }, { + }, + { "key": "top_left", "name": I18n.tr("options.launcher.position.top_left") - }, { + }, + { "key": "top_right", "name": I18n.tr("options.launcher.position.top_right") - }, { + }, + { "key": "bottom", "name": I18n.tr("options.launcher.position.bottom_center") - }, { + }, + { "key": "bottom_left", "name": I18n.tr("options.launcher.position.bottom_left") - }, { + }, + { "key": "bottom_right", "name": I18n.tr("options.launcher.position.bottom_right") - }] + } + ] currentKey: Settings.data.notifications.location || "top_right" onSelected: key => Settings.data.notifications.location = key } @@ -267,20 +274,20 @@ ColumnLayout { Layout.fillWidth: true label: modelData.name || I18n.tr("system.unknown") description: { - const compositorScale = CompositorService.getDisplayScale(modelData.name) + const compositorScale = CompositorService.getDisplayScale(modelData.name); I18n.tr("system.monitor-description", { "model": modelData.model, "width": modelData.width * compositorScale, "height": modelData.height * compositorScale, "scale": compositorScale - }) + }); } checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { - Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors, modelData.name) + Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors, modelData.name); } else { - Settings.data.notifications.monitors = removeMonitor(Settings.data.notifications.monitors, modelData.name) + Settings.data.notifications.monitors = removeMonitor(Settings.data.notifications.monitors, modelData.name); } } } diff --git a/Modules/Panels/Settings/Tabs/OsdTab.qml b/Modules/Panels/Settings/Tabs/OsdTab.qml index d3695411..9a6377df 100644 --- a/Modules/Panels/Settings/Tabs/OsdTab.qml +++ b/Modules/Panels/Settings/Tabs/OsdTab.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import qs.Commons import qs.Services.Compositor @@ -11,15 +11,15 @@ ColumnLayout { // Helper functions to update arrays immutably function addMonitor(list, name) { - const arr = (list || []).slice() + const arr = (list || []).slice(); if (!arr.includes(name)) - arr.push(name) - return arr + arr.push(name); + return arr; } function removeMonitor(list, name) { return (list || []).filter(function (n) { - return n !== name - }) + return n !== name; + }); } // Display @@ -30,31 +30,40 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.osd.location.label") description: I18n.tr("settings.osd.location.description") - model: [{ + model: [ + { "key": "top", "name": I18n.tr("options.osd.position.top_center") - }, { + }, + { "key": "top_left", "name": I18n.tr("options.osd.position.top_left") - }, { + }, + { "key": "top_right", "name": I18n.tr("options.osd.position.top_right") - }, { + }, + { "key": "bottom", "name": I18n.tr("options.osd.position.bottom_center") - }, { + }, + { "key": "bottom_left", "name": I18n.tr("options.osd.position.bottom_left") - }, { + }, + { "key": "bottom_right", "name": I18n.tr("options.osd.position.bottom_right") - }, { + }, + { "key": "left", "name": I18n.tr("options.osd.position.center_left") - }, { + }, + { "key": "right", "name": I18n.tr("options.osd.position.center_right") - }] + } + ] currentKey: Settings.data.osd.location || "top_right" onSelected: key => Settings.data.osd.location = key } @@ -143,20 +152,20 @@ ColumnLayout { Layout.fillWidth: true label: modelData.name || I18n.tr("system.unknown") description: { - const compositorScale = CompositorService.getDisplayScale(modelData.name) + const compositorScale = CompositorService.getDisplayScale(modelData.name); I18n.tr("system.monitor-description", { "model": modelData.model, "width": modelData.width * compositorScale, "height": modelData.height * compositorScale, "scale": compositorScale - }) + }); } checked: (Settings.data.osd.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { - Settings.data.osd.monitors = addMonitor(Settings.data.osd.monitors, modelData.name) + Settings.data.osd.monitors = addMonitor(Settings.data.osd.monitors, modelData.name); } else { - Settings.data.osd.monitors = removeMonitor(Settings.data.osd.monitors, modelData.name) + Settings.data.osd.monitors = removeMonitor(Settings.data.osd.monitors, modelData.name); } } } diff --git a/Modules/Panels/Settings/Tabs/ScreenRecorderTab.qml b/Modules/Panels/Settings/Tabs/ScreenRecorderTab.qml index 580af116..f0f9704a 100644 --- a/Modules/Panels/Settings/Tabs/ScreenRecorderTab.qml +++ b/Modules/Panels/Settings/Tabs/ScreenRecorderTab.qml @@ -60,13 +60,16 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.video-source.label") description: I18n.tr("settings.screen-recorder.video.video-source.description") - model: [{ + model: [ + { "key": "portal", "name": I18n.tr("options.screen-recording.sources.portal") - }, { + }, + { "key": "screen", "name": I18n.tr("options.screen-recording.sources.screen") - }] + } + ] currentKey: Settings.data.screenRecorder.videoSource onSelected: key => Settings.data.screenRecorder.videoSource = key } @@ -75,42 +78,50 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.frame-rate.label") description: I18n.tr("settings.screen-recorder.video.frame-rate.description") - model: [{ + model: [ + { "key": "30", "name": I18n.tr("options.frame-rates.fps", { "fps": "30" }) - }, { + }, + { "key": "60", "name": I18n.tr("options.frame-rates.fps", { "fps": "60" }) - }, { + }, + { "key": "100", "name": I18n.tr("options.frame-rates.fps", { "fps": "100" }) - }, { + }, + { "key": "120", "name": I18n.tr("options.frame-rates.fps", { "fps": "120" }) - }, { + }, + { "key": "144", "name": I18n.tr("options.frame-rates.fps", { "fps": "144" }) - }, { + }, + { "key": "165", "name": I18n.tr("options.frame-rates.fps", { "fps": "165" }) - }, { + }, + { "key": "240", "name": I18n.tr("options.frame-rates.fps", { "fps": "240" }) - }] + } + ] currentKey: Settings.data.screenRecorder.frameRate onSelected: key => Settings.data.screenRecorder.frameRate = key } @@ -119,19 +130,24 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.video-quality.label") description: I18n.tr("settings.screen-recorder.video.video-quality.description") - model: [{ + model: [ + { "key": "medium", "name": I18n.tr("options.screen-recording.quality.medium") - }, { + }, + { "key": "high", "name": I18n.tr("options.screen-recording.quality.high") - }, { + }, + { "key": "very_high", "name": I18n.tr("options.screen-recording.quality.very-high") - }, { + }, + { "key": "ultra", "name": I18n.tr("options.screen-recording.quality.ultra") - }] + } + ] currentKey: Settings.data.screenRecorder.quality onSelected: key => Settings.data.screenRecorder.quality = key } @@ -140,22 +156,28 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.video-codec.label") description: I18n.tr("settings.screen-recorder.video.video-codec.description") - model: [{ + model: [ + { "key": "h264", "name": "H264" - }, { + }, + { "key": "hevc", "name": "HEVC" - }, { + }, + { "key": "av1", "name": "AV1" - }, { + }, + { "key": "vp8", "name": "VP8" - }, { + }, + { "key": "vp9", "name": "VP9" - }] + } + ] currentKey: Settings.data.screenRecorder.videoCodec onSelected: key => Settings.data.screenRecorder.videoCodec = key } @@ -164,13 +186,16 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.color-range.label") description: I18n.tr("settings.screen-recorder.video.color-range.description") - model: [{ + model: [ + { "key": "limited", "name": I18n.tr("options.screen-recording.color-range.limited") - }, { + }, + { "key": "full", "name": I18n.tr("options.screen-recording.color-range.full") - }] + } + ] currentKey: Settings.data.screenRecorder.colorRange onSelected: key => Settings.data.screenRecorder.colorRange = key } @@ -196,16 +221,20 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.audio.audio-source.label") description: I18n.tr("settings.screen-recorder.audio.audio-source.description") - model: [{ + model: [ + { "key": "default_output", "name": I18n.tr("options.screen-recording.audio-sources.system-output") - }, { + }, + { "key": "default_input", "name": I18n.tr("options.screen-recording.audio-sources.microphone-input") - }, { + }, + { "key": "both", "name": I18n.tr("options.screen-recording.audio-sources.both") - }] + } + ] currentKey: Settings.data.screenRecorder.audioSource onSelected: key => Settings.data.screenRecorder.audioSource = key } @@ -214,13 +243,16 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.audio.audio-codec.label") description: I18n.tr("settings.screen-recorder.audio.audio-codec.description") - model: [{ + model: [ + { "key": "opus", "name": "Opus" - }, { + }, + { "key": "aac", "name": "AAC" - }] + } + ] currentKey: Settings.data.screenRecorder.audioCodec onSelected: key => Settings.data.screenRecorder.audioCodec = key } @@ -233,7 +265,7 @@ ColumnLayout { initialPath: Settings.data.screenRecorder.directory || Quickshell.env("HOME") + "/Videos" onAccepted: paths => { if (paths.length > 0) { - Settings.data.screenRecorder.directory = paths[0] // Use first selected file + Settings.data.screenRecorder.directory = paths[0]; // Use first selected file } } } diff --git a/Modules/Panels/Settings/Tabs/SessionMenuTab.qml b/Modules/Panels/Settings/Tabs/SessionMenuTab.qml index 884e5cb2..0770ad9d 100644 --- a/Modules/Panels/Settings/Tabs/SessionMenuTab.qml +++ b/Modules/Panels/Settings/Tabs/SessionMenuTab.qml @@ -12,87 +12,94 @@ ColumnLayout { spacing: Style.marginL property list entriesModel: [] - property list entriesDefault: [{ + property list entriesDefault: [ + { "id": "lock", "text": I18n.tr("session-menu.lock"), "enabled": true, "required": false - }, { + }, + { "id": "suspend", "text": I18n.tr("session-menu.suspend"), "enabled": true, "required": false - }, { + }, + { "id": "hibernate", "text": I18n.tr("session-menu.hibernate"), "enabled": true, "required": false - }, { + }, + { "id": "reboot", "text": I18n.tr("session-menu.reboot"), "enabled": true, "required": false - }, { + }, + { "id": "logout", "text": I18n.tr("session-menu.logout"), "enabled": true, "required": false - }, { + }, + { "id": "shutdown", "text": I18n.tr("session-menu.shutdown"), "enabled": true, "required": false - }] + } + ] function saveEntries() { - var toSave = [] + var toSave = []; for (var i = 0; i < entriesModel.length; i++) { toSave.push({ "action": entriesModel[i].id, "enabled": entriesModel[i].enabled, "countdownEnabled": entriesModel[i].countdownEnabled !== undefined ? entriesModel[i].countdownEnabled : true - }) + }); } - Settings.data.sessionMenu.powerOptions = toSave + Settings.data.sessionMenu.powerOptions = toSave; } Component.onCompleted: { - entriesModel = [] + entriesModel = []; // Add the entries available in settings for (var i = 0; i < Settings.data.sessionMenu.powerOptions.length; i++) { - const settingEntry = Settings.data.sessionMenu.powerOptions[i] + const settingEntry = Settings.data.sessionMenu.powerOptions[i]; for (var j = 0; j < entriesDefault.length; j++) { if (settingEntry.action === entriesDefault[j].id) { - var entry = entriesDefault[j] - entry.enabled = settingEntry.enabled + var entry = entriesDefault[j]; + entry.enabled = settingEntry.enabled; // Default countdownEnabled to true for backward compatibility - entry.countdownEnabled = settingEntry.countdownEnabled !== undefined ? settingEntry.countdownEnabled : true - entriesModel.push(entry) + entry.countdownEnabled = settingEntry.countdownEnabled !== undefined ? settingEntry.countdownEnabled : true; + entriesModel.push(entry); } } } // Add any missing entries from default for (var i = 0; i < entriesDefault.length; i++) { - var found = false + var found = false; for (var j = 0; j < entriesModel.length; j++) { if (entriesModel[j].id === entriesDefault[i].id) { - found = true - break + found = true; + break; } } if (!found) { - var entry = entriesDefault[i] + var entry = entriesDefault[i]; // Default countdownEnabled to true for new entries - entry.countdownEnabled = true - entriesModel.push(entry) + entry.countdownEnabled = true; + entriesModel.push(entry); } } - saveEntries() + saveEntries(); } NHeader { @@ -104,31 +111,39 @@ ColumnLayout { label: I18n.tr("settings.session-menu.position.label") description: I18n.tr("settings.session-menu.position.description") Layout.fillWidth: true - model: [{ + model: [ + { "key": "center", "name": I18n.tr("options.control-center.position.center") - }, { + }, + { "key": "top_center", "name": I18n.tr("options.control-center.position.top_center") - }, { + }, + { "key": "top_left", "name": I18n.tr("options.control-center.position.top_left") - }, { + }, + { "key": "top_right", "name": I18n.tr("options.control-center.position.top_right") - }, { + }, + { "key": "bottom_center", "name": I18n.tr("options.control-center.position.bottom_center") - }, { + }, + { "key": "bottom_left", "name": I18n.tr("options.control-center.position.bottom_left") - }, { + }, + { "key": "bottom_right", "name": I18n.tr("options.control-center.position.bottom_right") - }] + } + ] currentKey: Settings.data.sessionMenu.position onSelected: function (key) { - Settings.data.sessionMenu.position = key + Settings.data.sessionMenu.position = key; } } @@ -272,47 +287,47 @@ ColumnLayout { z: 1000 onPressed: mouse => { - delegateItem.dragStartIndex = delegateItem.index - delegateItem.dragTargetIndex = delegateItem.index - delegateItem.dragStartY = delegateItem.y - delegateItem.dragging = true - delegateItem.z = 999 - preventStealing = true + delegateItem.dragStartIndex = delegateItem.index; + delegateItem.dragTargetIndex = delegateItem.index; + delegateItem.dragStartY = delegateItem.y; + delegateItem.dragging = true; + delegateItem.z = 999; + preventStealing = true; } onPositionChanged: mouse => { if (delegateItem.dragging) { - var dy = mouse.y - height / 2 - var newY = delegateItem.y + dy - newY = Math.max(0, Math.min(newY, listView.contentHeight - delegateItem.height)) - delegateItem.y = newY - var targetIndex = Math.floor((newY + delegateItem.height / 2) / (delegateItem.height + Style.marginS)) - targetIndex = Math.max(0, Math.min(targetIndex, listView.count - 1)) - delegateItem.dragTargetIndex = targetIndex + var dy = mouse.y - height / 2; + var newY = delegateItem.y + dy; + newY = Math.max(0, Math.min(newY, listView.contentHeight - delegateItem.height)); + delegateItem.y = newY; + var targetIndex = Math.floor((newY + delegateItem.height / 2) / (delegateItem.height + Style.marginS)); + targetIndex = Math.max(0, Math.min(targetIndex, listView.count - 1)); + delegateItem.dragTargetIndex = targetIndex; } } onReleased: { - preventStealing = false + preventStealing = false; if (delegateItem.dragStartIndex !== -1 && delegateItem.dragTargetIndex !== -1 && delegateItem.dragStartIndex !== delegateItem.dragTargetIndex) { - var newModel = entriesModel.slice() - var item = newModel.splice(delegateItem.dragStartIndex, 1)[0] - newModel.splice(delegateItem.dragTargetIndex, 0, item) - entriesModel = newModel - root.saveEntries() + var newModel = entriesModel.slice(); + var item = newModel.splice(delegateItem.dragStartIndex, 1)[0]; + newModel.splice(delegateItem.dragTargetIndex, 0, item); + entriesModel = newModel; + root.saveEntries(); } - delegateItem.dragging = false - delegateItem.dragStartIndex = -1 - delegateItem.dragTargetIndex = -1 - delegateItem.z = 0 + delegateItem.dragging = false; + delegateItem.dragStartIndex = -1; + delegateItem.dragTargetIndex = -1; + delegateItem.z = 0; } onCanceled: { - preventStealing = false - delegateItem.dragging = false - delegateItem.dragStartIndex = -1 - delegateItem.dragTargetIndex = -1 - delegateItem.z = 0 + preventStealing = false; + delegateItem.dragging = false; + delegateItem.dragStartIndex = -1; + delegateItem.dragTargetIndex = -1; + delegateItem.z = 0; } } } @@ -346,12 +361,12 @@ ColumnLayout { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - var newModel = entriesModel.slice() + var newModel = entriesModel.slice(); newModel[index] = Object.assign({}, newModel[index], { "enabled": !modelData.enabled - }) - entriesModel = newModel - delegateItem.saveEntriesFunc() + }); + entriesModel = newModel; + delegateItem.saveEntriesFunc(); } } } @@ -380,12 +395,12 @@ ColumnLayout { NToggle { checked: modelData.countdownEnabled !== undefined ? modelData.countdownEnabled : true onToggled: function (checked) { - var newModel = entriesModel.slice() + var newModel = entriesModel.slice(); newModel[delegateItem.index] = Object.assign({}, newModel[delegateItem.index], { "countdownEnabled": checked - }) - entriesModel = newModel - delegateItem.saveEntriesFunc() + }); + entriesModel = newModel; + delegateItem.saveEntriesFunc(); } } } @@ -394,34 +409,34 @@ ColumnLayout { // Position binding for non-dragging state y: { if (delegateItem.dragging) { - return delegateItem.y + return delegateItem.y; } - var draggedIndex = -1 - var targetIndex = -1 + var draggedIndex = -1; + var targetIndex = -1; for (var i = 0; i < listView.count; i++) { - var item = listView.itemAtIndex(i) + var item = listView.itemAtIndex(i); if (item && item.dragging) { - draggedIndex = item.dragStartIndex - targetIndex = item.dragTargetIndex - break + draggedIndex = item.dragStartIndex; + targetIndex = item.dragTargetIndex; + break; } } if (draggedIndex !== -1 && targetIndex !== -1 && draggedIndex !== targetIndex) { - var currentIndex = delegateItem.index + var currentIndex = delegateItem.index; if (draggedIndex < targetIndex) { if (currentIndex > draggedIndex && currentIndex <= targetIndex) { - return (currentIndex - 1) * (delegateItem.height + Style.marginS) + return (currentIndex - 1) * (delegateItem.height + Style.marginS); } } else { if (currentIndex >= targetIndex && currentIndex < draggedIndex) { - return (currentIndex + 1) * (delegateItem.height + Style.marginS) + return (currentIndex + 1) * (delegateItem.height + Style.marginS); } } } - return delegateItem.index * (delegateItem.height + Style.marginS) + return delegateItem.index * (delegateItem.height + Style.marginS); } Behavior on y { diff --git a/Modules/Panels/Settings/Tabs/SystemMonitorTab.qml b/Modules/Panels/Settings/Tabs/SystemMonitorTab.qml index 9890e831..dca984c1 100644 --- a/Modules/Panels/Settings/Tabs/SystemMonitorTab.qml +++ b/Modules/Panels/Settings/Tabs/SystemMonitorTab.qml @@ -30,13 +30,13 @@ ColumnLayout { // If enabling custom colors and no custom color is saved, persist current theme colors if (checked) { if (!Settings.data.systemMonitor.warningColor || Settings.data.systemMonitor.warningColor === "") { - Settings.data.systemMonitor.warningColor = Color.mTertiary.toString() + Settings.data.systemMonitor.warningColor = Color.mTertiary.toString(); } if (!Settings.data.systemMonitor.criticalColor || Settings.data.systemMonitor.criticalColor === "") { - Settings.data.systemMonitor.criticalColor = Color.mError.toString() + Settings.data.systemMonitor.criticalColor = Color.mError.toString(); } } - Settings.data.systemMonitor.useCustomColors = checked + Settings.data.systemMonitor.useCustomColors = checked; } } } @@ -61,7 +61,7 @@ ColumnLayout { enabled: Settings.data.systemMonitor.useCustomColors selectedColor: Settings.data.systemMonitor.warningColor || Color.mTertiary onColorSelected: function (color) { - Settings.data.systemMonitor.warningColor = color + Settings.data.systemMonitor.warningColor = color; } } } @@ -81,7 +81,7 @@ ColumnLayout { enabled: Settings.data.systemMonitor.useCustomColors selectedColor: Settings.data.systemMonitor.criticalColor || Color.mError onColorSelected: function (color) { - Settings.data.systemMonitor.criticalColor = color + Settings.data.systemMonitor.criticalColor = color; } } } @@ -124,10 +124,10 @@ ColumnLayout { stepSize: 5 value: Settings.data.systemMonitor.cpuWarningThreshold onValueChanged: { - Settings.data.systemMonitor.cpuWarningThreshold = value + Settings.data.systemMonitor.cpuWarningThreshold = value; // Ensure critical >= warning if (Settings.data.systemMonitor.cpuCriticalThreshold < value) { - Settings.data.systemMonitor.cpuCriticalThreshold = value + Settings.data.systemMonitor.cpuCriticalThreshold = value; } } suffix: "%" @@ -181,9 +181,9 @@ ColumnLayout { stepSize: 5 value: Settings.data.systemMonitor.tempWarningThreshold onValueChanged: { - Settings.data.systemMonitor.tempWarningThreshold = value + Settings.data.systemMonitor.tempWarningThreshold = value; if (Settings.data.systemMonitor.tempCriticalThreshold < value) { - Settings.data.systemMonitor.tempCriticalThreshold = value + Settings.data.systemMonitor.tempCriticalThreshold = value; } } suffix: "°C" @@ -237,9 +237,9 @@ ColumnLayout { stepSize: 5 value: Settings.data.systemMonitor.memWarningThreshold onValueChanged: { - Settings.data.systemMonitor.memWarningThreshold = value + Settings.data.systemMonitor.memWarningThreshold = value; if (Settings.data.systemMonitor.memCriticalThreshold < value) { - Settings.data.systemMonitor.memCriticalThreshold = value + Settings.data.systemMonitor.memCriticalThreshold = value; } } suffix: "%" @@ -293,9 +293,9 @@ ColumnLayout { stepSize: 5 value: Settings.data.systemMonitor.diskWarningThreshold onValueChanged: { - Settings.data.systemMonitor.diskWarningThreshold = value + Settings.data.systemMonitor.diskWarningThreshold = value; if (Settings.data.systemMonitor.diskCriticalThreshold < value) { - Settings.data.systemMonitor.diskCriticalThreshold = value + Settings.data.systemMonitor.diskCriticalThreshold = value; } } suffix: "%" diff --git a/Modules/Panels/Settings/Tabs/UserInterfaceTab.qml b/Modules/Panels/Settings/Tabs/UserInterfaceTab.qml index 68206aed..c6438d92 100644 --- a/Modules/Panels/Settings/Tabs/UserInterfaceTab.qml +++ b/Modules/Panels/Settings/Tabs/UserInterfaceTab.qml @@ -118,17 +118,17 @@ ColumnLayout { return { "key": k, "name": shadowOptionsMap[k].name - } + }; }) currentKey: Settings.data.general.shadowDirection onSelected: function (key) { - var opt = shadowOptionsMap[key] + var opt = shadowOptionsMap[key]; if (opt) { - Settings.data.general.shadowDirection = key - Settings.data.general.shadowOffsetX = opt.p.x - Settings.data.general.shadowOffsetY = opt.p.y + Settings.data.general.shadowDirection = key; + Settings.data.general.shadowOffsetX = opt.p.x; + Settings.data.general.shadowOffsetY = opt.p.y; } } } diff --git a/Modules/Panels/Settings/Tabs/WallpaperTab.qml b/Modules/Panels/Settings/Tabs/WallpaperTab.qml index 7b7face9..2013d752 100644 --- a/Modules/Panels/Settings/Tabs/WallpaperTab.qml +++ b/Modules/Panels/Settings/Tabs/WallpaperTab.qml @@ -134,8 +134,8 @@ ColumnLayout { Layout.fillWidth: true onInputEditingFinished: WallpaperService.setMonitorDirectory(modelData.name, text) onButtonClicked: { - specificFolderMonitorName = modelData.name - monitorFolderPicker.open() + specificFolderMonitorName = modelData.name; + monitorFolderPicker.open(); } } } @@ -147,34 +147,43 @@ ColumnLayout { label: I18n.tr("settings.wallpaper.settings.selector-position.label") description: I18n.tr("settings.wallpaper.settings.selector-position.description") Layout.fillWidth: true - model: [{ + model: [ + { "key": "follow_bar", "name": I18n.tr("options.launcher.position.follow_bar") - }, { + }, + { "key": "center", "name": I18n.tr("options.launcher.position.center") - }, { + }, + { "key": "top_center", "name": I18n.tr("options.launcher.position.top_center") - }, { + }, + { "key": "top_left", "name": I18n.tr("options.launcher.position.top_left") - }, { + }, + { "key": "top_right", "name": I18n.tr("options.launcher.position.top_right") - }, { + }, + { "key": "bottom_left", "name": I18n.tr("options.launcher.position.bottom_left") - }, { + }, + { "key": "bottom_right", "name": I18n.tr("options.launcher.position.bottom_right") - }, { + }, + { "key": "bottom_center", "name": I18n.tr("options.launcher.position.bottom_center") - }] + } + ] currentKey: Settings.data.wallpaper.panelPosition onSelected: function (key) { - Settings.data.wallpaper.panelPosition = key + Settings.data.wallpaper.panelPosition = key; } } } @@ -313,21 +322,21 @@ ColumnLayout { // Whether current interval equals one of the presets property bool isCurrentPreset: { - return intervalPresets.some(seconds => seconds === Settings.data.wallpaper.randomIntervalSec) + return intervalPresets.some(seconds => seconds === Settings.data.wallpaper.randomIntervalSec); } // Allow user to force open the custom input; otherwise it's auto-open when not a preset property bool customForcedVisible: false function setIntervalSeconds(sec) { - Settings.data.wallpaper.randomIntervalSec = sec - WallpaperService.restartRandomWallpaperTimer() + Settings.data.wallpaper.randomIntervalSec = sec; + WallpaperService.restartRandomWallpaperTimer(); // Hide custom when selecting a preset - customForcedVisible = false + customForcedVisible = false; } // Helper to color selected chip function isSelected(sec) { - return Settings.data.wallpaper.randomIntervalSec === sec + return Settings.data.wallpaper.randomIntervalSec === sec; } // Repeater for preset chips @@ -360,24 +369,24 @@ ColumnLayout { label: I18n.tr("settings.wallpaper.automation.custom-interval.label") description: I18n.tr("settings.wallpaper.automation.custom-interval.description") text: { - const s = Settings.data.wallpaper.randomIntervalSec - const h = Math.floor(s / 3600) - const m = Math.floor((s % 3600) / 60) - return h + ":" + (m < 10 ? ("0" + m) : m) + const s = Settings.data.wallpaper.randomIntervalSec; + const h = Math.floor(s / 3600); + const m = Math.floor((s % 3600) / 60); + return h + ":" + (m < 10 ? ("0" + m) : m); } onEditingFinished: { - const m = text.trim().match(/^(\d{1,2}):(\d{2})$/) + const m = text.trim().match(/^(\d{1,2}):(\d{2})$/); if (m) { - let h = parseInt(m[1]) - let min = parseInt(m[2]) + let h = parseInt(m[1]); + let min = parseInt(m[2]); if (isNaN(h) || isNaN(min)) - return - h = Math.max(0, Math.min(24, h)) - min = Math.max(0, Math.min(59, min)) - Settings.data.wallpaper.randomIntervalSec = (h * 3600) + (min * 60) - WallpaperService.restartRandomWallpaperTimer() + return; + h = Math.max(0, Math.min(24, h)); + min = Math.max(0, Math.min(59, min)); + Settings.data.wallpaper.randomIntervalSec = (h * 3600) + (min * 60); + WallpaperService.restartRandomWallpaperTimer(); // Keep custom visible after manual entry - presetRow.customForcedVisible = true + presetRow.customForcedVisible = true; } } } @@ -427,7 +436,7 @@ ColumnLayout { initialPath: Settings.data.wallpaper.directory || Quickshell.env("HOME") + "/Pictures" onAccepted: paths => { if (paths.length > 0) { - Settings.data.wallpaper.directory = paths[0] + Settings.data.wallpaper.directory = paths[0]; } } } @@ -439,7 +448,7 @@ ColumnLayout { initialPath: WallpaperService.getMonitorDirectory(specificFolderMonitorName) || Quickshell.env("HOME") + "/Pictures" onAccepted: paths => { if (paths.length > 0) { - WallpaperService.setMonitorDirectory(specificFolderMonitorName, paths[0]) + WallpaperService.setMonitorDirectory(specificFolderMonitorName, paths[0]); } } } diff --git a/Modules/Panels/SetupWizard/SetupAppearanceStep.qml b/Modules/Panels/SetupWizard/SetupAppearanceStep.qml index 56621419..21e64f4c 100644 --- a/Modules/Panels/SetupWizard/SetupAppearanceStep.qml +++ b/Modules/Panels/SetupWizard/SetupAppearanceStep.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell.Io import qs.Commons import qs.Services.System @@ -12,8 +12,8 @@ ColumnLayout { spacing: Style.marginM function extractSchemeName(path) { - var basename = path.split('/').pop() - return basename.replace('.json', '') + var basename = path.split('/').pop(); + return basename.replace('.json', ''); } // Cache for scheme colors (mirrors ColorSchemeTab approach) @@ -22,30 +22,28 @@ ColumnLayout { function getSchemeColor(schemeName, key) { try { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var data = schemeColorsCache[schemeName] + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; + var data = schemeColorsCache[schemeName]; if (data && data[mode] && data[mode][key]) - return data[mode][key] - } catch (e) { - - } - return Color.mSurfaceVariant + return data[mode][key]; + } catch (e) {} + return Color.mSurfaceVariant; } // Match ColorSchemeTab helpers function schemeLoaded(schemeName, jsonData) { - var value = jsonData || {} - schemeColorsCache[schemeName] = value - cacheVersion++ - Logger.i("SetupAppearanceStep", `Loaded scheme ${schemeName}`) + var value = jsonData || {}; + schemeColorsCache[schemeName] = value; + cacheVersion++; + Logger.i("SetupAppearanceStep", `Loaded scheme ${schemeName}`); } Connections { target: ColorSchemeService function onSchemesChanged() { - Logger.i("SetupAppearanceStep", `Color schemes changed: ${ColorSchemeService.schemes.length}`) - schemeColorsCache = {} - cacheVersion++ + Logger.i("SetupAppearanceStep", `Color schemes changed: ${ColorSchemeService.schemes.length}`); + schemeColorsCache = {}; + cacheVersion++; } } @@ -200,14 +198,14 @@ ColumnLayout { checked: Settings.data.colorSchemes.useWallpaperColors && ProgramCheckerService.matugenAvailable onToggled: checked => { if (!ProgramCheckerService.matugenAvailable) - return + return; if (checked) { - Settings.data.colorSchemes.useWallpaperColors = true - AppThemeService.generate() + Settings.data.colorSchemes.useWallpaperColors = true; + AppThemeService.generate(); } else { - Settings.data.colorSchemes.useWallpaperColors = false + Settings.data.colorSchemes.useWallpaperColors = false; if (Settings.data.colorSchemes.predefinedScheme) { - ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme); } } } @@ -265,31 +263,40 @@ ColumnLayout { columnSpacing: Style.marginS Repeater { - model: [{ + model: [ + { "key": "scheme-content", "name": "Content" - }, { + }, + { "key": "scheme-expressive", "name": "Expressive" - }, { + }, + { "key": "scheme-fidelity", "name": "Fidelity" - }, { + }, + { "key": "scheme-fruit-salad", "name": "Fruit Salad" - }, { + }, + { "key": "scheme-monochrome", "name": "Monochrome" - }, { + }, + { "key": "scheme-neutral", "name": "Neutral" - }, { + }, + { "key": "scheme-rainbow", "name": "Rainbow" - }, { + }, + { "key": "scheme-tonal-spot", "name": "Tonal Spot" - }] + } + ] delegate: Rectangle { Layout.fillWidth: true Layout.preferredHeight: 48 @@ -317,8 +324,8 @@ ColumnLayout { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - Settings.data.colorSchemes.matugenSchemeType = modelData.key - AppThemeService.generate() + Settings.data.colorSchemes.matugenSchemeType = modelData.key; + AppThemeService.generate(); } } @@ -443,9 +450,9 @@ ColumnLayout { height: 14 radius: width * 0.5 color: root.cacheVersion >= 0 ? (function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mPrimary) || root.getSchemeColor(schemeItem.schemeName, "mPrimary") + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; + var cached = root.schemeColorsCache[schemeItem.schemeName]; + return (cached && cached[mode] && cached[mode].mPrimary) || root.getSchemeColor(schemeItem.schemeName, "mPrimary"); })() : Color.mPrimary } Rectangle { @@ -453,9 +460,9 @@ ColumnLayout { height: 14 radius: width * 0.5 color: root.cacheVersion >= 0 ? (function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mSecondary) || root.getSchemeColor(schemeItem.schemeName, "mSecondary") + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; + var cached = root.schemeColorsCache[schemeItem.schemeName]; + return (cached && cached[mode] && cached[mode].mSecondary) || root.getSchemeColor(schemeItem.schemeName, "mSecondary"); })() : Color.mSecondary } Rectangle { @@ -463,9 +470,9 @@ ColumnLayout { height: 14 radius: width * 0.5 color: root.cacheVersion >= 0 ? (function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mTertiary) || root.getSchemeColor(schemeItem.schemeName, "mTertiary") + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; + var cached = root.schemeColorsCache[schemeItem.schemeName]; + return (cached && cached[mode] && cached[mode].mTertiary) || root.getSchemeColor(schemeItem.schemeName, "mTertiary"); })() : Color.mTertiary } Rectangle { @@ -473,9 +480,9 @@ ColumnLayout { height: 14 radius: width * 0.5 color: root.cacheVersion >= 0 ? (function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mError) || root.getSchemeColor(schemeItem.schemeName, "mError") + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; + var cached = root.schemeColorsCache[schemeItem.schemeName]; + return (cached && cached[mode] && cached[mode].mError) || root.getSchemeColor(schemeItem.schemeName, "mError"); })() : Color.mError } } @@ -486,9 +493,9 @@ ColumnLayout { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { - Settings.data.colorSchemes.useWallpaperColors = false - Settings.data.colorSchemes.predefinedScheme = schemeItem.schemeName - ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + Settings.data.colorSchemes.useWallpaperColors = false; + Settings.data.colorSchemes.predefinedScheme = schemeItem.schemeName; + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme); } } } @@ -514,12 +521,12 @@ ColumnLayout { path: modelData blockLoading: false onLoaded: { - var schemeName = root.extractSchemeName(path) + var schemeName = root.extractSchemeName(path); try { - var jsonData = JSON.parse(text()) - root.schemeLoaded(schemeName, jsonData) + var jsonData = JSON.parse(text()); + root.schemeLoaded(schemeName, jsonData); } catch (e) { - root.schemeLoaded(schemeName, null) + root.schemeLoaded(schemeName, null); } } } diff --git a/Modules/Panels/SetupWizard/SetupCustomizeStep.qml b/Modules/Panels/SetupWizard/SetupCustomizeStep.qml index c99a0c2e..e14f860d 100644 --- a/Modules/Panels/SetupWizard/SetupCustomizeStep.qml +++ b/Modules/Panels/SetupWizard/SetupCustomizeStep.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import qs.Commons import qs.Widgets @@ -115,23 +115,28 @@ ColumnLayout { spacing: Style.marginS Repeater { - model: [{ + model: [ + { "key": "top", "name": I18n.tr("options.bar.position.top"), "icon": "arrow-up" - }, { + }, + { "key": "bottom", "name": I18n.tr("options.bar.position.bottom"), "icon": "arrow-down" - }, { + }, + { "key": "left", "name": I18n.tr("options.bar.position.left"), "icon": "arrow-left" - }, { + }, + { "key": "right", "name": I18n.tr("options.bar.position.right"), "icon": "arrow-right" - }] + } + ] delegate: Rectangle { Layout.fillWidth: true Layout.preferredHeight: 40 @@ -159,8 +164,8 @@ ColumnLayout { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - selectedBarPosition = modelData.key - barPositionChanged(modelData.key) + selectedBarPosition = modelData.key; + barPositionChanged(modelData.key); } } @@ -233,19 +238,24 @@ ColumnLayout { RowLayout { spacing: Style.marginS Repeater { - model: [{ + model: [ + { "key": "mini", "name": I18n.tr("options.bar.density.mini") - }, { + }, + { "key": "compact", "name": I18n.tr("options.bar.density.compact") - }, { + }, + { "key": "default", "name": I18n.tr("options.bar.density.default") - }, { + }, + { "key": "comfortable", "name": I18n.tr("options.bar.density.comfortable") - }] + } + ] delegate: Rectangle { radius: 16 border.width: 1 @@ -274,7 +284,7 @@ ColumnLayout { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - Settings.data.bar.density = modelData.key + Settings.data.bar.density = modelData.key; } } @@ -352,8 +362,8 @@ ColumnLayout { stepSize: 0.05 value: selectedScaleRatio onMoved: function (value) { - selectedScaleRatio = value - scaleRatioChanged(value) + selectedScaleRatio = value; + scaleRatioChanged(value); } text: Math.floor(selectedScaleRatio * 100) + "%" } @@ -405,7 +415,7 @@ ColumnLayout { NToggle { checked: Settings.data.bar.floating onToggled: function (checked) { - Settings.data.bar.floating = checked + Settings.data.bar.floating = checked; } } } @@ -435,7 +445,7 @@ ColumnLayout { stepSize: 0.01 value: Settings.data.bar.backgroundOpacity onMoved: function (value) { - Settings.data.bar.backgroundOpacity = value + Settings.data.bar.backgroundOpacity = value; } text: Math.floor(Settings.data.bar.backgroundOpacity * 100) + "%" } @@ -542,7 +552,7 @@ ColumnLayout { NToggle { checked: Settings.data.general.enableShadows onToggled: function (checked) { - Settings.data.general.enableShadows = checked + Settings.data.general.enableShadows = checked; } } } diff --git a/Modules/Panels/SetupWizard/SetupDockStep.qml b/Modules/Panels/SetupWizard/SetupDockStep.qml index 3b3e3168..de98771c 100644 --- a/Modules/Panels/SetupWizard/SetupDockStep.qml +++ b/Modules/Panels/SetupWizard/SetupDockStep.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import qs.Commons import qs.Services.Compositor @@ -70,16 +70,20 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.dock.appearance.display.label") description: I18n.tr("settings.dock.appearance.display.description") - model: [{ + model: [ + { "key": "always_visible", "name": I18n.tr("settings.dock.appearance.display.always-visible") - }, { + }, + { "key": "auto_hide", "name": I18n.tr("settings.dock.appearance.display.auto-hide") - }, { + }, + { "key": "exclusive", "name": I18n.tr("settings.dock.appearance.display.exclusive") - }] + } + ] currentKey: Settings.data.dock.displayMode onSelected: key => Settings.data.dock.displayMode = key } @@ -176,25 +180,25 @@ ColumnLayout { label: modelData.name || "Unknown" visible: Settings.data.dock.enabled description: { - const compositorScale = CompositorService.getDisplayScale(modelData.name) + const compositorScale = CompositorService.getDisplayScale(modelData.name); I18n.tr("system.monitor-description", { "model": modelData.model, "width": modelData.width * compositorScale, "height": modelData.height * compositorScale, "scale": compositorScale - }) + }); } checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { - const arr = (Settings.data.dock.monitors || []).slice() + const arr = (Settings.data.dock.monitors || []).slice(); if (arr.indexOf(modelData.name) === -1) - arr.push(modelData.name) - Settings.data.dock.monitors = arr + arr.push(modelData.name); + Settings.data.dock.monitors = arr; } else { Settings.data.dock.monitors = (Settings.data.dock.monitors || []).filter(function (n) { - return n !== modelData.name - }) + return n !== modelData.name; + }); } } } diff --git a/Modules/Panels/SetupWizard/SetupWallpaperStep.qml b/Modules/Panels/SetupWizard/SetupWallpaperStep.qml index a2f10166..e453bc7d 100644 --- a/Modules/Panels/SetupWizard/SetupWallpaperStep.qml +++ b/Modules/Panels/SetupWizard/SetupWallpaperStep.qml @@ -1,13 +1,13 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls import QtQuick.Effects +import QtQuick.Layouts import Quickshell import Quickshell.Io +import "../../../Helpers/FuzzySort.js" as FuzzySort import qs.Commons import qs.Services.UI import qs.Widgets -import "../../../Helpers/FuzzySort.js" as FuzzySort ColumnLayout { id: root @@ -209,20 +209,20 @@ ColumnLayout { target: galleryScroll.contentItem acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad onWheel: event => { - const flick = galleryScroll.contentItem + const flick = galleryScroll.contentItem; if (!flick) - return - const delta = event.pixelDelta.x !== 0 || event.pixelDelta.y !== 0 ? (event.pixelDelta.y !== 0 ? event.pixelDelta.y : event.pixelDelta.x) : (event.angleDelta.y !== 0 ? event.angleDelta.y : event.angleDelta.x) + return; + const delta = event.pixelDelta.x !== 0 || event.pixelDelta.y !== 0 ? (event.pixelDelta.y !== 0 ? event.pixelDelta.y : event.pixelDelta.x) : (event.angleDelta.y !== 0 ? event.angleDelta.y : event.angleDelta.x); // Move opposite of wheel to scroll content to the right for wheel down - const step = -delta - const maxX = Math.max(0, flick.contentWidth - flick.width) - let newX = flick.contentX + step + const step = -delta; + const maxX = Math.max(0, flick.contentWidth - flick.width); + let newX = flick.contentX + step; if (newX < 0) - newX = 0 + newX = 0; if (newX > maxX) - newX = maxX - flick.contentX = newX - event.accepted = true + newX = maxX; + flick.contentX = newX; + event.accepted = true; } } @@ -319,8 +319,8 @@ ColumnLayout { TapHandler { onTapped: { - selectedWallpaper = modelData - wallpaperChanged(modelData) + selectedWallpaper = modelData; + wallpaperChanged(modelData); } } } @@ -386,8 +386,8 @@ ColumnLayout { buttonTooltip: I18n.tr("setup.wallpaper.dir.browse") Layout.fillWidth: true onInputEditingFinished: { - selectedDirectory = text - directoryChanged(text) + selectedDirectory = text; + directoryChanged(text); } onButtonClicked: directoryPicker.open() } @@ -398,41 +398,41 @@ ColumnLayout { property list filteredWallpapers: [] function updateFilteredWallpapers() { - filteredWallpapers = wallpapersList + filteredWallpapers = wallpapersList; } function refreshWallpapers() { if (!selectedDirectory || selectedDirectory === "") { - wallpapersList = [] - filteredWallpapers = [] - return + wallpapersList = []; + filteredWallpapers = []; + return; } if (typeof WallpaperService !== "undefined" && WallpaperService.getWallpapersList) { - var wallpapers = WallpaperService.getWallpapersList(Screen.name) - wallpapersList = wallpapers - updateFilteredWallpapers() + var wallpapers = WallpaperService.getWallpapersList(Screen.name); + wallpapersList = wallpapers; + updateFilteredWallpapers(); if (wallpapersList.length > 0 && selectedWallpaper === "") { - selectedWallpaper = wallpapersList[0] + selectedWallpaper = wallpapersList[0]; } } else { - readDirectoryImages(selectedDirectory) + readDirectoryImages(selectedDirectory); } } function readDirectoryImages(directoryPath) { - directoryScanner.command = ["find", directoryPath, "-type", "f", "\\(-iname", "*.jpg", "-o", "-iname", "*.jpeg", "-o", "-iname", "*.png", "-o", "-iname", "*.bmp", "-o", "-iname", "*.webp", "-o", "-iname", "*.svg", "\\)"] - directoryScanner.running = true - return [] + directoryScanner.command = ["find", directoryPath, "-type", "f", "\\(-iname", "*.jpg", "-o", "-iname", "*.jpeg", "-o", "-iname", "*.png", "-o", "-iname", "*.bmp", "-o", "-iname", "*.webp", "-o", "-iname", "*.svg", "\\)"]; + directoryScanner.running = true; + return []; } onSelectedDirectoryChanged: { if (typeof Settings !== "undefined" && Settings.data && Settings.data.wallpaper) { - Settings.data.wallpaper.directory = selectedDirectory + Settings.data.wallpaper.directory = selectedDirectory; } if (typeof WallpaperService !== "undefined" && WallpaperService.refreshWallpapersList) { - WallpaperService.refreshWallpapersList() + WallpaperService.refreshWallpapersList(); } - Qt.callLater(refreshWallpapers) + Qt.callLater(refreshWallpapers); } Connections { @@ -440,7 +440,7 @@ ColumnLayout { enabled: typeof WallpaperService !== "undefined" function onWallpaperListChanged(screenName, count) { if (screenName === Screen.name) { - Qt.callLater(refreshWallpapers) + Qt.callLater(refreshWallpapers); } } } @@ -455,14 +455,14 @@ ColumnLayout { Component.onCompleted: { if (typeof Settings !== "undefined" && Settings.data && Settings.data.wallpaper && Settings.data.wallpaper.directory) { - selectedDirectory = Settings.data.wallpaper.directory + selectedDirectory = Settings.data.wallpaper.directory; } else { - selectedDirectory = Quickshell.env("HOME") + "/Pictures/Wallpapers" + selectedDirectory = Quickshell.env("HOME") + "/Pictures/Wallpapers"; } if (typeof WallpaperService !== "undefined" && WallpaperService.currentWallpaper) { - selectedWallpaper = WallpaperService.currentWallpaper + selectedWallpaper = WallpaperService.currentWallpaper; } - initialRefreshTimer.start() + initialRefreshTimer.start(); } NFilePicker { @@ -472,8 +472,8 @@ ColumnLayout { initialPath: selectedDirectory || Quickshell.env("HOME") + "/Pictures" onAccepted: paths => { if (paths.length > 0) { - selectedDirectory = paths[0] - directoryChanged(paths[0]) + selectedDirectory = paths[0]; + directoryChanged(paths[0]); } } } @@ -486,18 +486,18 @@ ColumnLayout { stderr: StdioCollector {} onExited: function (exitCode) { if (exitCode === 0) { - var lines = stdout.text.split('\n') - var images = [] + var lines = stdout.text.split('\n'); + var images = []; for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim() + var line = lines[i].trim(); if (line !== '') { - images.push(line) + images.push(line); } } - wallpapersList = images - updateFilteredWallpapers() + wallpapersList = images; + updateFilteredWallpapers(); if (wallpapersList.length > 0 && selectedWallpaper === "") { - selectedWallpaper = wallpapersList[0] + selectedWallpaper = wallpapersList[0]; } } } diff --git a/Modules/Panels/SetupWizard/SetupWizard.qml b/Modules/Panels/SetupWizard/SetupWizard.qml index e8515152..a914fd96 100644 --- a/Modules/Panels/SetupWizard/SetupWizard.qml +++ b/Modules/Panels/SetupWizard/SetupWizard.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Wayland import qs.Commons @@ -26,9 +26,9 @@ SmartPanel { property int totalSteps: 5 onOpened: function () { - selectedScaleRatio = Settings.data.general.scaleRatio - selectedBarPosition = Settings.data.bar.position - selectedWallpaperDirectory = Settings.data.wallpaper.directory || Settings.defaultWallpapersDirectory + selectedScaleRatio = Settings.data.general.scaleRatio; + selectedBarPosition = Settings.data.bar.position; + selectedWallpaperDirectory = Settings.data.wallpaper.directory || Settings.defaultWallpapersDirectory; } // Setup wizard data @@ -179,12 +179,12 @@ SmartPanel { selectedDirectory: root.selectedWallpaperDirectory selectedWallpaper: root.selectedWallpaper onDirectoryChanged: function (directory) { - root.selectedWallpaperDirectory = directory - root.applyWallpaperSettings() + root.selectedWallpaperDirectory = directory; + root.applyWallpaperSettings(); } onWallpaperChanged: function (wallpaper) { - root.selectedWallpaper = wallpaper - root.applyWallpaperSettings() + root.selectedWallpaper = wallpaper; + root.applyWallpaperSettings(); } } @@ -199,12 +199,12 @@ SmartPanel { selectedScaleRatio: root.selectedScaleRatio selectedBarPosition: root.selectedBarPosition onScaleRatioChanged: function (ratio) { - root.selectedScaleRatio = ratio - root.applyUISettings() + root.selectedScaleRatio = ratio; + root.applyUISettings(); } onBarPositionChanged: function (position) { - root.selectedBarPosition = position - root.applyUISettings() + root.selectedBarPosition = position; + root.applyUISettings(); } } @@ -233,22 +233,28 @@ SmartPanel { spacing: Style.marginM Repeater { - model: [{ + model: [ + { "icon": "sparkles", "label": "Welcome" - }, { + }, + { "icon": "image", "label": "Wallpaper" - }, { + }, + { "icon": "palette", "label": "Appearance" - }, { + }, + { "icon": "settings", "label": "Customize" - }, { + }, + { "icon": "device-desktop", "label": "Dock" - }] + } + ] delegate: RowLayout { spacing: Style.marginS @@ -322,7 +328,7 @@ SmartPanel { visible: currentStep === 0 Layout.preferredHeight: 44 onClicked: { - root.completeSetup() + root.completeSetup(); } } @@ -337,7 +343,7 @@ SmartPanel { Layout.preferredHeight: 44 onClicked: { if (currentStep > 0) { - currentStep-- + currentStep--; } } } @@ -347,9 +353,9 @@ SmartPanel { Layout.preferredHeight: 44 onClicked: { if (currentStep < totalSteps - 1) { - currentStep++ + currentStep++; } else { - root.completeSetup() + root.completeSetup(); } } } @@ -360,39 +366,39 @@ SmartPanel { } function completeSetup() { - Logger.i("SetupWizard", "Completing setup with selected options") + Logger.i("SetupWizard", "Completing setup with selected options"); if (selectedWallpaperDirectory !== Settings.data.wallpaper.directory) { - Settings.data.wallpaper.directory = selectedWallpaperDirectory - WallpaperService.refreshWallpapersList() + Settings.data.wallpaper.directory = selectedWallpaperDirectory; + WallpaperService.refreshWallpapersList(); } if (selectedWallpaper !== "") { - WallpaperService.changeWallpaper(selectedWallpaper, undefined) + WallpaperService.changeWallpaper(selectedWallpaper, undefined); } - Settings.data.general.scaleRatio = selectedScaleRatio - Settings.data.bar.position = selectedBarPosition - Settings.data.setupCompleted = true + Settings.data.general.scaleRatio = selectedScaleRatio; + Settings.data.bar.position = selectedBarPosition; + Settings.data.setupCompleted = true; - Settings.saveImmediate() - Logger.i("SetupWizard", "Setup completed successfully") - root.close() + Settings.saveImmediate(); + Logger.i("SetupWizard", "Setup completed successfully"); + root.close(); } function applyWallpaperSettings() { if (selectedWallpaperDirectory !== Settings.data.wallpaper.directory) { - Settings.data.wallpaper.directory = selectedWallpaperDirectory - WallpaperService.refreshWallpapersList() + Settings.data.wallpaper.directory = selectedWallpaperDirectory; + WallpaperService.refreshWallpapersList(); } if (selectedWallpaper !== "") { - WallpaperService.changeWallpaper(selectedWallpaper, undefined) + WallpaperService.changeWallpaper(selectedWallpaper, undefined); } } function applyUISettings() { - Settings.data.general.scaleRatio = selectedScaleRatio - Settings.data.bar.position = selectedBarPosition + Settings.data.general.scaleRatio = selectedScaleRatio; + Settings.data.bar.position = selectedBarPosition; } } diff --git a/Modules/Panels/Tray/TrayDrawerPanel.qml b/Modules/Panels/Tray/TrayDrawerPanel.qml index bf30a3e6..53d9245e 100644 --- a/Modules/Panels/Tray/TrayDrawerPanel.qml +++ b/Modules/Panels/Tray/TrayDrawerPanel.qml @@ -1,12 +1,12 @@ import QtQuick import QtQuick.Layouts import Quickshell -import Quickshell.Widgets import Quickshell.Services.SystemTray +import Quickshell.Widgets import qs.Commons +import qs.Modules.MainScreen import qs.Services.UI import qs.Widgets -import qs.Modules.MainScreen // A compact grid panel listing all tray items, opened from the Tray widget SmartPanel { @@ -25,16 +25,16 @@ SmartPanel { // Read widget settings for reactivity readonly property var widgetSettings: { // Reference settingsVersion to force recalculation when it changes - var _ = root.settingsVersion + var _ = root.settingsVersion; if (widgetSection === "" || widgetIndex < 0) - return {} - var widgets = Settings.data.bar.widgets[widgetSection] + return {}; + var widgets = Settings.data.bar.widgets[widgetSection]; if (!widgets || widgetIndex >= widgets.length) - return {} - var settings = widgets[widgetIndex] + return {}; + var settings = widgets[widgetIndex]; if (!settings || settings.id !== "Tray") - return {} - return settings + return {}; + return settings; } // Read pinned list directly from settings for reactivity @@ -42,32 +42,32 @@ SmartPanel { function wildCardMatch(str, rule) { if (!str || !rule) - return false - let escaped = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - let pattern = '^' + escaped.replace(/\\\*/g, '.*') + '$' + return false; + let escaped = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + let pattern = '^' + escaped.replace(/\\\*/g, '.*') + '$'; try { - return new RegExp(pattern, 'i').test(str) + return new RegExp(pattern, 'i').test(str); } catch (e) { - return false + return false; } } function isPinned(item) { if (!pinnedList || pinnedList.length === 0) - return false - const title = item?.tooltipTitle || item?.name || item?.id || "" + return false; + const title = item?.tooltipTitle || item?.name || item?.id || ""; for (var i = 0; i < pinnedList.length; i++) { if (wildCardMatch(title, pinnedList[i])) - return true + return true; } - return false + return false; } // Dynamic sizing based on item count // Show items that are NOT pinned (unpinned items go to drawer) readonly property var trayValuesAll: (SystemTray.items && SystemTray.items.values) ? SystemTray.items.values : [] readonly property var trayValues: trayValuesAll.filter(function (it) { - return !root.isPinned(it) + return !root.isPinned(it); }) readonly property int itemCount: trayValues.length readonly property int maxColumns: 8 @@ -88,14 +88,14 @@ SmartPanel { target: Settings function onSettingsSaved() { // Force refresh by incrementing settingsVersion, which triggers recalculation of pinnedList - root.settingsVersion++ + root.settingsVersion++; } } // Auto-close drawer when all items are pinned (drawer becomes empty) onTrayValuesChanged: { if (visible && trayValues.length === 0) { - close() + close(); } } @@ -105,8 +105,8 @@ SmartPanel { // Get the trayMenu window and loader from PanelService (reactive to trigger changes) readonly property var trayMenuWindow: { // Reference trigger to force re-evaluation - var _ = trayMenuUpdateTrigger - return PanelService.getTrayMenuWindow(screen) + var _ = trayMenuUpdateTrigger; + return PanelService.getTrayMenuWindow(screen); } readonly property var trayMenu: trayMenuWindow ? trayMenuWindow.trayMenuLoader : null @@ -115,7 +115,7 @@ SmartPanel { target: PanelService function onTrayMenuWindowRegistered(registeredScreen) { if (registeredScreen === screen) { - root.trayMenuUpdateTrigger++ + root.trayMenuUpdateTrigger++; } } } @@ -150,17 +150,17 @@ SmartPanel { asynchronous: true backer.fillMode: Image.PreserveAspectFit source: { - let icon = modelData?.icon || "" + let icon = modelData?.icon || ""; if (!icon) - return "" + return ""; if (icon.includes("?path=")) { - const chunks = icon.split("?path=") - const name = chunks[0] - const path = chunks[1] - const fileName = name.substring(name.lastIndexOf("/") + 1) - return `file://${path}/${fileName}` + const chunks = icon.split("?path="); + const name = chunks[0]; + const path = chunks[1]; + const fileName = name.substring(name.lastIndexOf("/") + 1); + return `file://${path}/${fileName}`; } - return icon + return icon; } layer.enabled: root.widgetSettings.colorizeIcons !== false @@ -178,65 +178,64 @@ SmartPanel { onClicked: mouse => { if (!modelData) - return - + return; if (mouse.button === Qt.LeftButton) { // Left click: activate tray item if (!modelData.onlyMenu) { - modelData.activate() + modelData.activate(); } } else if (mouse.button === Qt.MiddleButton) { // Middle click: activate with middle button - modelData.secondaryActivate && modelData.secondaryActivate() + modelData.secondaryActivate && modelData.secondaryActivate(); } else if (mouse.button === Qt.RightButton) { // Right click: open context menu - TooltipService.hideImmediately() + TooltipService.hideImmediately(); // Close menu if already visible if (trayMenuWindow && trayMenuWindow.visible) { - trayMenuWindow.close() - return + trayMenuWindow.close(); + return; } if (modelData.hasMenu && modelData.menu && trayMenuWindow && trayMenu && trayMenu.item) { - trayMenuWindow.open() + trayMenuWindow.open(); // Position menu at the tray icon - const barPosition = Settings.data.bar.position - let menuX, menuY + const barPosition = Settings.data.bar.position; + let menuX, menuY; if (barPosition === "left") { - menuX = trayIcon.width + Style.marginM - menuY = 0 + menuX = trayIcon.width + Style.marginM; + menuY = 0; } else if (barPosition === "right") { - menuX = -trayMenu.item.width - Style.marginM - menuY = 0 + menuX = -trayMenu.item.width - Style.marginM; + menuY = 0; } else { // Horizontal bars - menuX = (trayIcon.width / 2) - (trayMenu.item.width / 2) - menuY = trayIcon.height + Style.marginS + menuX = (trayIcon.width / 2) - (trayMenu.item.width / 2); + menuY = trayIcon.height + Style.marginS; } - trayMenu.item.trayItem = modelData - trayMenu.item.widgetSection = root.widgetSection - trayMenu.item.widgetIndex = root.widgetIndex - trayMenu.item.showAt(trayIcon, menuX, menuY) + trayMenu.item.trayItem = modelData; + trayMenu.item.widgetSection = root.widgetSection; + trayMenu.item.widgetIndex = root.widgetIndex; + trayMenu.item.showAt(trayIcon, menuX, menuY); } } } onWheel: wheel => { if (wheel.angleDelta.y > 0) - modelData?.scrollUp() + modelData?.scrollUp(); else if (wheel.angleDelta.y < 0) - modelData?.scrollDown() + modelData?.scrollDown(); } onEntered: { if (trayMenuWindow) { - trayMenuWindow.close() + trayMenuWindow.close(); } - TooltipService.show(Screen, trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection()) + TooltipService.show(Screen, trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection()); } onExited: TooltipService.hide() } diff --git a/Modules/Panels/Wallpaper/WallhavenSettingsPopup.qml b/Modules/Panels/Wallpaper/WallhavenSettingsPopup.qml index 454efa4f..8ec64064 100644 --- a/Modules/Panels/Wallpaper/WallhavenSettingsPopup.qml +++ b/Modules/Panels/Wallpaper/WallhavenSettingsPopup.qml @@ -22,72 +22,72 @@ Popup { x: { if (anchorItem) { - var itemPos = anchorItem.mapToItem(parent, 0, 0) - return itemPos.x - width + anchorItem.width + var itemPos = anchorItem.mapToItem(parent, 0, 0); + return itemPos.x - width + anchorItem.width; } - return 0 + return 0; } y: { if (anchorItem) { - var itemPos = anchorItem.mapToItem(parent, 0, 0) - return itemPos.y + anchorItem.height + Style.marginS + var itemPos = anchorItem.mapToItem(parent, 0, 0); + return itemPos.y + anchorItem.height + Style.marginS; } - return 0 + return 0; } function showAt(item) { if (!item) { - return + return; } - anchorItem = item - open() + anchorItem = item; + open(); Qt.callLater(() => { // Try to focus the first input if available if (resolutionWidthInput.inputItem) { - resolutionWidthInput.inputItem.forceActiveFocus() + resolutionWidthInput.inputItem.forceActiveFocus(); } - }) + }); } onOpened: { Qt.callLater(() => { if (resolutionWidthInput.inputItem) { - resolutionWidthInput.inputItem.forceActiveFocus() + resolutionWidthInput.inputItem.forceActiveFocus(); } - }) + }); } function hide() { - close() + close(); } function updateResolution(triggerSearch) { if (typeof WallhavenService === "undefined") { - return + return; } - var width = Settings.data.wallpaper.wallhavenResolutionWidth || "" - var height = Settings.data.wallpaper.wallhavenResolutionHeight || "" - var mode = Settings.data.wallpaper.wallhavenResolutionMode || "atleast" + var width = Settings.data.wallpaper.wallhavenResolutionWidth || ""; + var height = Settings.data.wallpaper.wallhavenResolutionHeight || ""; + var mode = Settings.data.wallpaper.wallhavenResolutionMode || "atleast"; if (width && height) { - var resolution = width + "x" + height + var resolution = width + "x" + height; if (mode === "atleast") { - WallhavenService.minResolution = resolution - WallhavenService.resolutions = "" + WallhavenService.minResolution = resolution; + WallhavenService.resolutions = ""; } else { - WallhavenService.minResolution = "" - WallhavenService.resolutions = resolution + WallhavenService.minResolution = ""; + WallhavenService.resolutions = resolution; } } else { - WallhavenService.minResolution = "" - WallhavenService.resolutions = "" + WallhavenService.minResolution = ""; + WallhavenService.resolutions = ""; } // Trigger new search with updated resolution only if requested if (triggerSearch && Settings.data.wallpaper.useWallhaven) { - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); } } @@ -154,31 +154,38 @@ Popup { id: sortingComboBox Layout.fillWidth: true Layout.minimumWidth: 200 - model: [{ + model: [ + { "key": "date_added", "name": I18n.tr("wallpaper.panel.sorting.date_added") - }, { + }, + { "key": "relevance", "name": I18n.tr("wallpaper.panel.sorting.relevance") - }, { + }, + { "key": "random", "name": I18n.tr("wallpaper.panel.sorting.random") - }, { + }, + { "key": "views", "name": I18n.tr("wallpaper.panel.sorting.views") - }, { + }, + { "key": "favorites", "name": I18n.tr("wallpaper.panel.sorting.favorites") - }, { + }, + { "key": "toplist", "name": I18n.tr("wallpaper.panel.sorting.toplist") - }] + } + ] currentKey: Settings.data.wallpaper.wallhavenSorting || "relevance" onSelected: key => { - Settings.data.wallpaper.wallhavenSorting = key + Settings.data.wallpaper.wallhavenSorting = key; if (typeof WallhavenService !== "undefined") { - WallhavenService.sorting = key - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + WallhavenService.sorting = key; + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); } } } @@ -201,19 +208,22 @@ Popup { id: orderComboBox Layout.fillWidth: true Layout.minimumWidth: 200 - model: [{ + model: [ + { "key": "desc", "name": I18n.tr("wallpaper.panel.order.desc") - }, { + }, + { "key": "asc", "name": I18n.tr("wallpaper.panel.order.asc") - }] + } + ] currentKey: Settings.data.wallpaper.wallhavenOrder || "desc" onSelected: key => { - Settings.data.wallpaper.wallhavenOrder = key + Settings.data.wallpaper.wallhavenOrder = key; if (typeof WallhavenService !== "undefined") { - WallhavenService.order = key - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + WallhavenService.order = key; + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); } } } @@ -235,22 +245,26 @@ Popup { id: purityComboBox Layout.fillWidth: true Layout.minimumWidth: 200 - model: [{ + model: [ + { "key": "111", "name": I18n.tr("wallpaper.panel.purity.all") - }, { + }, + { "key": "100", "name": I18n.tr("wallpaper.panel.purity.sfw") - }, { + }, + { "key": "010", "name": I18n.tr("wallpaper.panel.purity.sketchy") - }] + } + ] currentKey: Settings.data.wallpaper.wallhavenPurity onSelected: key => { - Settings.data.wallpaper.wallhavenPurity = key + Settings.data.wallpaper.wallhavenPurity = key; if (typeof WallhavenService !== "undefined") { - WallhavenService.purity = key - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + WallhavenService.purity = key; + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); } } } @@ -277,36 +291,36 @@ Popup { spacing: Style.marginL function getCategoryValue(index) { - var cats = Settings.data.wallpaper.wallhavenCategories || "111" - return cats.length > index && cats.charAt(index) === "1" + var cats = Settings.data.wallpaper.wallhavenCategories || "111"; + return cats.length > index && cats.charAt(index) === "1"; } function updateCategories(general, anime, people) { - var categories = (general ? "1" : "0") + (anime ? "1" : "0") + (people ? "1" : "0") - Settings.data.wallpaper.wallhavenCategories = categories + var categories = (general ? "1" : "0") + (anime ? "1" : "0") + (people ? "1" : "0"); + Settings.data.wallpaper.wallhavenCategories = categories; // Update checkboxes immediately - generalToggle.checked = general - animeToggle.checked = anime - peopleToggle.checked = people + generalToggle.checked = general; + animeToggle.checked = anime; + peopleToggle.checked = people; if (typeof WallhavenService !== "undefined") { - WallhavenService.categories = categories - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery, 1) + WallhavenService.categories = categories; + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery, 1); } } Connections { target: Settings.data.wallpaper function onWallhavenCategoriesChanged() { - generalToggle.checked = categoriesRow.getCategoryValue(0) - animeToggle.checked = categoriesRow.getCategoryValue(1) - peopleToggle.checked = categoriesRow.getCategoryValue(2) + generalToggle.checked = categoriesRow.getCategoryValue(0); + animeToggle.checked = categoriesRow.getCategoryValue(1); + peopleToggle.checked = categoriesRow.getCategoryValue(2); } } Component.onCompleted: { - generalToggle.checked = categoriesRow.getCategoryValue(0) - animeToggle.checked = categoriesRow.getCategoryValue(1) - peopleToggle.checked = categoriesRow.getCategoryValue(2) + generalToggle.checked = categoriesRow.getCategoryValue(0); + animeToggle.checked = categoriesRow.getCategoryValue(1); + peopleToggle.checked = categoriesRow.getCategoryValue(2); } // General checkbox @@ -462,7 +476,7 @@ Popup { property bool checked: false signal toggled(bool checked) onToggled: checked => { - categoriesRow.updateCategories(checked, categoriesRow.getCategoryValue(1), categoriesRow.getCategoryValue(2)) + categoriesRow.updateCategories(checked, categoriesRow.getCategoryValue(1), categoriesRow.getCategoryValue(2)); } } @@ -471,7 +485,7 @@ Popup { property bool checked: false signal toggled(bool checked) onToggled: checked => { - categoriesRow.updateCategories(categoriesRow.getCategoryValue(0), checked, categoriesRow.getCategoryValue(2)) + categoriesRow.updateCategories(categoriesRow.getCategoryValue(0), checked, categoriesRow.getCategoryValue(2)); } } @@ -480,7 +494,7 @@ Popup { property bool checked: false signal toggled(bool checked) onToggled: checked => { - categoriesRow.updateCategories(categoriesRow.getCategoryValue(0), categoriesRow.getCategoryValue(1), checked) + categoriesRow.updateCategories(categoriesRow.getCategoryValue(0), categoriesRow.getCategoryValue(1), checked); } } } @@ -512,27 +526,30 @@ Popup { id: resolutionModeComboBox Layout.fillWidth: true Layout.minimumWidth: 200 - model: [{ + model: [ + { "key": "atleast", "name": I18n.tr("wallpaper.panel.resolution.atleast") - }, { + }, + { "key": "exact", "name": I18n.tr("wallpaper.panel.resolution.exact") - }] + } + ] currentKey: Settings.data.wallpaper.wallhavenResolutionMode || "atleast" Connections { target: Settings.data.wallpaper function onWallhavenResolutionModeChanged() { if (resolutionModeComboBox.currentKey !== Settings.data.wallpaper.wallhavenResolutionMode) { - resolutionModeComboBox.currentKey = Settings.data.wallpaper.wallhavenResolutionMode || "atleast" + resolutionModeComboBox.currentKey = Settings.data.wallpaper.wallhavenResolutionMode || "atleast"; } } } onSelected: key => { - Settings.data.wallpaper.wallhavenResolutionMode = key - updateResolution(false) + Settings.data.wallpaper.wallhavenResolutionMode = key; + updateResolution(false); } } } @@ -550,16 +567,16 @@ Popup { Component.onCompleted: { if (resolutionWidthInput.inputItem) { - resolutionWidthInput.inputItem.focusPolicy = Qt.StrongFocus + resolutionWidthInput.inputItem.focusPolicy = Qt.StrongFocus; // Ensure the TextField can receive keyboard input - resolutionWidthInput.inputItem.activeFocusOnPress = true + resolutionWidthInput.inputItem.activeFocusOnPress = true; } } // Ensure focus when clicked onActiveFocusChanged: { if (activeFocus && resolutionWidthInput.inputItem) { - resolutionWidthInput.inputItem.forceActiveFocus() + resolutionWidthInput.inputItem.forceActiveFocus(); } } @@ -567,14 +584,14 @@ Popup { target: Settings.data.wallpaper function onWallhavenResolutionWidthChanged() { if (resolutionWidthInput.text !== Settings.data.wallpaper.wallhavenResolutionWidth) { - resolutionWidthInput.text = Settings.data.wallpaper.wallhavenResolutionWidth || "" + resolutionWidthInput.text = Settings.data.wallpaper.wallhavenResolutionWidth || ""; } } } onEditingFinished: { - Settings.data.wallpaper.wallhavenResolutionWidth = text - updateResolution(false) + Settings.data.wallpaper.wallhavenResolutionWidth = text; + updateResolution(false); } } @@ -594,15 +611,15 @@ Popup { Component.onCompleted: { if (resolutionHeightInput.inputItem) { - resolutionHeightInput.inputItem.focusPolicy = Qt.StrongFocus - resolutionHeightInput.inputItem.activeFocusOnPress = true + resolutionHeightInput.inputItem.focusPolicy = Qt.StrongFocus; + resolutionHeightInput.inputItem.activeFocusOnPress = true; } } // Ensure focus when clicked onActiveFocusChanged: { if (activeFocus && resolutionHeightInput.inputItem) { - resolutionHeightInput.inputItem.forceActiveFocus() + resolutionHeightInput.inputItem.forceActiveFocus(); } } @@ -610,14 +627,14 @@ Popup { target: Settings.data.wallpaper function onWallhavenResolutionHeightChanged() { if (resolutionHeightInput.text !== Settings.data.wallpaper.wallhavenResolutionHeight) { - resolutionHeightInput.text = Settings.data.wallpaper.wallhavenResolutionHeight || "" + resolutionHeightInput.text = Settings.data.wallpaper.wallhavenResolutionHeight || ""; } } } onEditingFinished: { - Settings.data.wallpaper.wallhavenResolutionHeight = text - updateResolution(false) + Settings.data.wallpaper.wallhavenResolutionHeight = text; + updateResolution(false); } } } @@ -636,21 +653,21 @@ Popup { // Ensure all settings are synced to the service if (typeof WallhavenService !== "undefined" && Settings.data.wallpaper.useWallhaven) { // Sync all settings to the service - WallhavenService.categories = Settings.data.wallpaper.wallhavenCategories - WallhavenService.purity = Settings.data.wallpaper.wallhavenPurity - WallhavenService.sorting = Settings.data.wallpaper.wallhavenSorting - WallhavenService.order = Settings.data.wallpaper.wallhavenOrder + WallhavenService.categories = Settings.data.wallpaper.wallhavenCategories; + WallhavenService.purity = Settings.data.wallpaper.wallhavenPurity; + WallhavenService.sorting = Settings.data.wallpaper.wallhavenSorting; + WallhavenService.order = Settings.data.wallpaper.wallhavenOrder; // Update resolution settings (without triggering search) - updateResolution(false) + updateResolution(false); // Refresh the wallpaper search with current settings - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); // Close the popup after applying (delay to prevent click propagation) Qt.callLater(() => { - root.hide() - }) + root.hide(); + }); } } } diff --git a/Modules/Panels/Wallpaper/WallpaperPanel.qml b/Modules/Panels/Wallpaper/WallpaperPanel.qml index ea32701d..6e34e110 100644 --- a/Modules/Panels/Wallpaper/WallpaperPanel.qml +++ b/Modules/Panels/Wallpaper/WallpaperPanel.qml @@ -1,13 +1,13 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell +import "../../../Helpers/FuzzySort.js" as FuzzySort import qs.Commons import qs.Modules.MainScreen import qs.Modules.Panels.Settings import qs.Services.UI import qs.Widgets -import "../../../Helpers/FuzzySort.js" as FuzzySort SmartPanel { id: root @@ -21,12 +21,12 @@ SmartPanel { readonly property string panelPosition: { if (Settings.data.wallpaper.panelPosition === "follow_bar") { if (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") { - return `center_${Settings.data.bar.position}` + return `center_${Settings.data.bar.position}`; } else { - return `${Settings.data.bar.position}_center` + return `${Settings.data.bar.position}_center`; } } else { - return Settings.data.wallpaper.panelPosition + return Settings.data.wallpaper.panelPosition; } } panelAnchorHorizontalCenter: panelPosition === "center" || panelPosition.endsWith("_center") @@ -42,59 +42,59 @@ SmartPanel { // Override keyboard handlers to enable grid navigation function onDownPressed() { if (!contentItem) - return - let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex) + return; + let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex); if (view?.gridView) { if (!view.gridView.activeFocus) { - view.gridView.forceActiveFocus() + view.gridView.forceActiveFocus(); if (view.gridView.currentIndex < 0) { - view.gridView.currentIndex = 0 + view.gridView.currentIndex = 0; } } else { - view.gridView.moveCurrentIndexDown() + view.gridView.moveCurrentIndexDown(); } } } function onUpPressed() { if (!contentItem) - return - let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex) + return; + let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex); if (view?.gridView?.activeFocus) { - view.gridView.moveCurrentIndexUp() + view.gridView.moveCurrentIndexUp(); } } function onLeftPressed() { if (!contentItem) - return - let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex) + return; + let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex); if (view?.gridView?.activeFocus) { - view.gridView.moveCurrentIndexLeft() + view.gridView.moveCurrentIndexLeft(); } } function onRightPressed() { if (!contentItem) - return - let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex) + return; + let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex); if (view?.gridView?.activeFocus) { - view.gridView.moveCurrentIndexRight() + view.gridView.moveCurrentIndexRight(); } } function onReturnPressed() { if (!contentItem) - return - let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex) + return; + let view = contentItem.screenRepeater.itemAt(contentItem.currentScreenIndex); if (view?.gridView?.activeFocus) { - let gridView = view.gridView + let gridView = view.gridView; if (gridView.currentIndex >= 0 && gridView.currentIndex < gridView.model.length) { - let path = gridView.model[gridView.currentIndex] + let path = gridView.model[gridView.currentIndex]; if (Settings.data.wallpaper.setWallpaperOnAllMonitors) { - WallpaperService.changeWallpaper(path, undefined) + WallpaperService.changeWallpaper(path, undefined); } else { - WallpaperService.changeWallpaper(path, view.targetScreen.name) + WallpaperService.changeWallpaper(path, view.targetScreen.name); } } } @@ -107,50 +107,50 @@ SmartPanel { if (screen !== null) { for (var i = 0; i < Quickshell.screens.length; i++) { if (Quickshell.screens[i].name == screen.name) { - return i + return i; } } } - return 0 + return 0; } property var currentScreen: Quickshell.screens[currentScreenIndex] property string filterText: "" property alias screenRepeater: screenRepeater Component.onCompleted: { - root.contentItem = wallpaperPanel + root.contentItem = wallpaperPanel; } // Function to update Wallhaven resolution filter function updateWallhavenResolution() { if (typeof WallhavenService === "undefined") { - return + return; } - var width = Settings.data.wallpaper.wallhavenResolutionWidth || "" - var height = Settings.data.wallpaper.wallhavenResolutionHeight || "" - var mode = Settings.data.wallpaper.wallhavenResolutionMode || "atleast" + var width = Settings.data.wallpaper.wallhavenResolutionWidth || ""; + var height = Settings.data.wallpaper.wallhavenResolutionHeight || ""; + var mode = Settings.data.wallpaper.wallhavenResolutionMode || "atleast"; if (width && height) { - var resolution = width + "x" + height + var resolution = width + "x" + height; if (mode === "atleast") { - WallhavenService.minResolution = resolution - WallhavenService.resolutions = "" + WallhavenService.minResolution = resolution; + WallhavenService.resolutions = ""; } else { - WallhavenService.minResolution = "" - WallhavenService.resolutions = resolution + WallhavenService.minResolution = ""; + WallhavenService.resolutions = resolution; } } else { - WallhavenService.minResolution = "" - WallhavenService.resolutions = "" + WallhavenService.minResolution = ""; + WallhavenService.resolutions = ""; } // Trigger new search with updated resolution if (Settings.data.wallpaper.useWallhaven) { if (wallhavenView) { - wallhavenView.loading = true + wallhavenView.loading = true; } - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); } } @@ -162,7 +162,7 @@ SmartPanel { source: "WallhavenSettingsPopup.qml" onLoaded: { if (item) { - item.screen = screen + item.screen = screen; } } } @@ -173,14 +173,14 @@ SmartPanel { function onOpened() { // Ensure contentItem is set if (!root.contentItem) { - root.contentItem = wallpaperPanel + root.contentItem = wallpaperPanel; } // Give initial focus to search input Qt.callLater(() => { if (searchInput.inputItem) { - searchInput.inputItem.forceActiveFocus() + searchInput.inputItem.forceActiveFocus(); } - }) + }); } } @@ -189,12 +189,12 @@ SmartPanel { id: searchDebounceTimer interval: 150 onTriggered: { - wallpaperPanel.filterText = searchInput.text + wallpaperPanel.filterText = searchInput.text; // Trigger update on all screen views for (var i = 0; i < screenRepeater.count; i++) { - let item = screenRepeater.itemAt(i) + let item = screenRepeater.itemAt(i); if (item && item.updateFiltered) { - item.updateFiltered() + item.updateFiltered(); } } } @@ -229,9 +229,9 @@ SmartPanel { tooltipText: I18n.tr("settings.wallpaper.settings.section.label") baseSize: Style.baseWidgetSize * 0.8 onClicked: { - var settingsPanel = PanelService.getPanel("settingsPanel", screen) - settingsPanel.requestedTab = SettingsPanel.Tab.Wallpaper - settingsPanel.open() + var settingsPanel = PanelService.getPanel("settingsPanel", screen); + settingsPanel.requestedTab = SettingsPanel.Tab.Wallpaper; + settingsPanel.open(); } } @@ -242,10 +242,10 @@ SmartPanel { onClicked: { if (Settings.data.wallpaper.useWallhaven) { if (typeof WallhavenService !== "undefined") { - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery, 1) + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery, 1); } } else { - WallpaperService.refreshWallpapersList() + WallpaperService.refreshWallpapersList(); } } } @@ -267,10 +267,10 @@ SmartPanel { id: wallhavenSearchDebounceTimer interval: 500 onTriggered: { - Settings.data.wallpaper.wallhavenQuery = searchInput.text + Settings.data.wallpaper.wallhavenQuery = searchInput.text; if (typeof WallhavenService !== "undefined") { - wallhavenView.loading = true - WallhavenService.search(searchInput.text, 1) + wallhavenView.loading = true; + WallhavenService.search(searchInput.text, 1); } } } @@ -300,7 +300,7 @@ SmartPanel { text: modelData.name || `Screen ${index + 1}` tabIndex: index checked: { - screenTabBar.currentIndex === index + screenTabBar.currentIndex === index; } } } @@ -320,18 +320,18 @@ SmartPanel { Component.onCompleted: { // Initialize text based on current mode if (Settings.data.wallpaper.useWallhaven) { - searchInput.text = Settings.data.wallpaper.wallhavenQuery || "" + searchInput.text = Settings.data.wallpaper.wallhavenQuery || ""; } else { - searchInput.text = wallpaperPanel.filterText || "" + searchInput.text = wallpaperPanel.filterText || ""; } // Give focus to search input if (searchInput.inputItem && searchInput.inputItem.visible) { - searchInput.inputItem.forceActiveFocus() + searchInput.inputItem.forceActiveFocus(); } // Mark initialization as complete after a short delay Qt.callLater(function () { - searchInput.initializing = false - }) + searchInput.initializing = false; + }); } Connections { @@ -339,9 +339,9 @@ SmartPanel { function onUseWallhavenChanged() { // Update text when mode changes if (Settings.data.wallpaper.useWallhaven) { - searchInput.text = Settings.data.wallpaper.wallhavenQuery || "" + searchInput.text = Settings.data.wallpaper.wallhavenQuery || ""; } else { - searchInput.text = wallpaperPanel.filterText || "" + searchInput.text = wallpaperPanel.filterText || ""; } } } @@ -349,22 +349,22 @@ SmartPanel { onTextChanged: { // Don't trigger search during initialization - Component.onCompleted will handle initial search if (initializing) { - return + return; } if (Settings.data.wallpaper.useWallhaven) { - wallhavenSearchDebounceTimer.restart() + wallhavenSearchDebounceTimer.restart(); } else { - searchDebounceTimer.restart() + searchDebounceTimer.restart(); } } onEditingFinished: { if (Settings.data.wallpaper.useWallhaven) { - wallhavenSearchDebounceTimer.stop() - Settings.data.wallpaper.wallhavenQuery = text + wallhavenSearchDebounceTimer.stop(); + Settings.data.wallpaper.wallhavenQuery = text; if (typeof WallhavenService !== "undefined") { - wallhavenView.loading = true - WallhavenService.search(text, 1) + wallhavenView.loading = true; + WallhavenService.search(text, 1); } } } @@ -372,12 +372,12 @@ SmartPanel { Keys.onDownPressed: { if (Settings.data.wallpaper.useWallhaven) { if (wallhavenView && wallhavenView.gridView) { - wallhavenView.gridView.forceActiveFocus() + wallhavenView.gridView.forceActiveFocus(); } } else { - let currentView = screenRepeater.itemAt(currentScreenIndex) + let currentView = screenRepeater.itemAt(currentScreenIndex); if (currentView && currentView.gridView) { - currentView.gridView.forceActiveFocus() + currentView.gridView.forceActiveFocus(); } } } @@ -387,50 +387,53 @@ SmartPanel { id: sourceComboBox Layout.fillWidth: false - model: [{ + model: [ + { "key": "local", "name": I18n.tr("wallpaper.panel.source.local") - }, { + }, + { "key": "wallhaven", "name": I18n.tr("wallpaper.panel.source.wallhaven") - }] + } + ] currentKey: Settings.data.wallpaper.useWallhaven ? "wallhaven" : "local" property bool skipNextSelected: false Component.onCompleted: { // Skip the first onSelected if it fires during initialization - skipNextSelected = true + skipNextSelected = true; Qt.callLater(function () { - skipNextSelected = false - }) + skipNextSelected = false; + }); } onSelected: key => { if (skipNextSelected) { - return + return; } - var useWallhaven = (key === "wallhaven") - Settings.data.wallpaper.useWallhaven = useWallhaven + var useWallhaven = (key === "wallhaven"); + Settings.data.wallpaper.useWallhaven = useWallhaven; // Update search input text based on mode if (useWallhaven) { - searchInput.text = Settings.data.wallpaper.wallhavenQuery || "" + searchInput.text = Settings.data.wallpaper.wallhavenQuery || ""; } else { - searchInput.text = wallpaperPanel.filterText || "" + searchInput.text = wallpaperPanel.filterText || ""; } if (useWallhaven && typeof WallhavenService !== "undefined") { // Update service properties when switching to Wallhaven // Don't search here - Component.onCompleted will handle it when the component is created // This prevents duplicate searches - WallhavenService.categories = Settings.data.wallpaper.wallhavenCategories - WallhavenService.purity = Settings.data.wallpaper.wallhavenPurity - WallhavenService.sorting = Settings.data.wallpaper.wallhavenSorting - WallhavenService.order = Settings.data.wallpaper.wallhavenOrder + WallhavenService.categories = Settings.data.wallpaper.wallhavenCategories; + WallhavenService.purity = Settings.data.wallpaper.wallhavenPurity; + WallhavenService.sorting = Settings.data.wallpaper.wallhavenSorting; + WallhavenService.order = Settings.data.wallpaper.wallhavenOrder; // Update resolution settings - wallpaperPanel.updateWallhavenResolution() + wallpaperPanel.updateWallhavenResolution(); // If the view is already initialized, trigger a new search when switching to it if (wallhavenView && wallhavenView.initialized && !WallhavenService.fetching) { - wallhavenView.loading = true - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + wallhavenView.loading = true; + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); } } } @@ -445,10 +448,10 @@ SmartPanel { visible: Settings.data.wallpaper.useWallhaven onClicked: { if (searchInput.inputItem) { - searchInput.inputItem.focus = false + searchInput.inputItem.focus = false; } if (wallhavenSettingsPopup.item) { - wallhavenSettingsPopup.item.showAt(wallhavenSettingsButton) + wallhavenSettingsPopup.item.showAt(wallhavenSettingsButton); } } } @@ -497,60 +500,60 @@ SmartPanel { // Expose updateFiltered as a proper function property function updateFiltered() { if (!wallpaperPanel.filterText || wallpaperPanel.filterText.trim().length === 0) { - filteredWallpapers = wallpapersList - return + filteredWallpapers = wallpapersList; + return; } const results = FuzzySort.go(wallpaperPanel.filterText.trim(), wallpapersWithNames, { "key": 'name', "limit": 200 - }) + }); // Map back to path list filteredWallpapers = results.map(function (r) { - return r.obj.path - }) + return r.obj.path; + }); } Component.onCompleted: { - refreshWallpaperScreenData() + refreshWallpaperScreenData(); } Connections { target: WallpaperService function onWallpaperChanged(screenName, path) { if (targetScreen !== null && screenName === targetScreen.name) { - currentWallpaper = WallpaperService.getWallpaper(targetScreen.name) + currentWallpaper = WallpaperService.getWallpaper(targetScreen.name); } } function onWallpaperDirectoryChanged(screenName, directory) { if (targetScreen !== null && screenName === targetScreen.name) { - refreshWallpaperScreenData() + refreshWallpaperScreenData(); } } function onWallpaperListChanged(screenName, count) { if (targetScreen !== null && screenName === targetScreen.name) { - refreshWallpaperScreenData() + refreshWallpaperScreenData(); } } } function refreshWallpaperScreenData() { if (targetScreen === null) { - return + return; } - wallpapersList = WallpaperService.getWallpapersList(targetScreen.name) - Logger.d("WallpaperPanel", "Got", wallpapersList.length, "wallpapers for screen", targetScreen.name) + wallpapersList = WallpaperService.getWallpapersList(targetScreen.name); + Logger.d("WallpaperPanel", "Got", wallpapersList.length, "wallpapers for screen", targetScreen.name); // Pre-compute basenames once for better performance wallpapersWithNames = wallpapersList.map(function (p) { return { "path": p, "name": p.split('/').pop() - } - }) + }; + }); - currentWallpaper = WallpaperService.getWallpaper(targetScreen.name) - updateFiltered() + currentWallpaper = WallpaperService.getWallpaper(targetScreen.name); + updateFiltered(); } ColumnLayout { @@ -577,9 +580,9 @@ SmartPanel { anchors.fill: parent z: -1 onClicked: { - wallpaperGridView.forceActiveFocus() + wallpaperGridView.forceActiveFocus(); if (wallpaperGridView.currentIndex < 0 && filteredWallpapers.length > 0) { - wallpaperGridView.currentIndex = 0 + wallpaperGridView.currentIndex = 0; } } } @@ -598,16 +601,16 @@ SmartPanel { onCurrentIndexChanged: { // Synchronize scroll with current item position if (currentIndex >= 0) { - let row = Math.floor(currentIndex / columns) - let itemY = row * cellHeight - let viewportTop = contentY - let viewportBottom = viewportTop + height + let row = Math.floor(currentIndex / columns); + let itemY = row * cellHeight; + let viewportTop = contentY; + let viewportBottom = viewportTop + height; // If item is out of view, scroll if (itemY < viewportTop) { - contentY = Math.max(0, itemY - cellHeight) + contentY = Math.max(0, itemY - cellHeight); } else if (itemY + cellHeight > viewportBottom) { - contentY = itemY + cellHeight - height + cellHeight + contentY = itemY + cellHeight - height + cellHeight; } } } @@ -615,14 +618,14 @@ SmartPanel { Keys.onPressed: event => { if (event.key === Qt.Key_Return || event.key === Qt.Key_Space) { if (currentIndex >= 0 && currentIndex < filteredWallpapers.length) { - let path = filteredWallpapers[currentIndex] + let path = filteredWallpapers[currentIndex]; if (Settings.data.wallpaper.setWallpaperOnAllMonitors) { - WallpaperService.changeWallpaper(path, undefined) + WallpaperService.changeWallpaper(path, undefined); } else { - WallpaperService.changeWallpaper(path, targetScreen.name) + WallpaperService.changeWallpaper(path, targetScreen.name); } } - event.accepted = true + event.accepted = true; } } @@ -702,12 +705,12 @@ SmartPanel { color: Color.transparent border.color: { if (isSelected) { - return Color.mSecondary + return Color.mSecondary; } if (wallpaperGridView.currentIndex === index) { - return Color.mHover + return Color.mHover; } - return Color.mSurface + return Color.mSurface; } border.width: Math.max(1, Style.borderL * 1.5) } @@ -751,12 +754,12 @@ SmartPanel { TapHandler { onTapped: { - wallpaperGridView.forceActiveFocus() - wallpaperGridView.currentIndex = index + wallpaperGridView.forceActiveFocus(); + wallpaperGridView.currentIndex = index; if (Settings.data.wallpaper.setWallpaperOnAllMonitors) { - WallpaperService.changeWallpaper(wallpaperPath, undefined) + WallpaperService.changeWallpaper(wallpaperPath, undefined); } else { - WallpaperService.changeWallpaper(wallpaperPath, targetScreen.name) + WallpaperService.changeWallpaper(wallpaperPath, targetScreen.name); } } } @@ -841,15 +844,15 @@ SmartPanel { Connections { target: typeof WallhavenService !== "undefined" ? WallhavenService : null function onSearchCompleted(results, meta) { - wallhavenViewRoot.wallpapers = results || [] - wallhavenViewRoot.loading = false - wallhavenViewRoot.errorMessage = "" - wallhavenViewRoot.searchScheduled = false + wallhavenViewRoot.wallpapers = results || []; + wallhavenViewRoot.loading = false; + wallhavenViewRoot.errorMessage = ""; + wallhavenViewRoot.searchScheduled = false; } function onSearchFailed(error) { - wallhavenViewRoot.loading = false - wallhavenViewRoot.errorMessage = error || "" - wallhavenViewRoot.searchScheduled = false + wallhavenViewRoot.loading = false; + wallhavenViewRoot.errorMessage = error || ""; + wallhavenViewRoot.searchScheduled = false; } } @@ -859,39 +862,39 @@ SmartPanel { // Set flags immediately to prevent race conditions if (WallhavenService.initialSearchScheduled) { // Another instance already scheduled the search, just initialize properties - initialized = true - return + initialized = true; + return; } // We're the first one - claim the search - initialized = true - WallhavenService.initialSearchScheduled = true - WallhavenService.categories = Settings.data.wallpaper.wallhavenCategories - WallhavenService.purity = Settings.data.wallpaper.wallhavenPurity - WallhavenService.sorting = Settings.data.wallpaper.wallhavenSorting - WallhavenService.order = Settings.data.wallpaper.wallhavenOrder + initialized = true; + WallhavenService.initialSearchScheduled = true; + WallhavenService.categories = Settings.data.wallpaper.wallhavenCategories; + WallhavenService.purity = Settings.data.wallpaper.wallhavenPurity; + WallhavenService.sorting = Settings.data.wallpaper.wallhavenSorting; + WallhavenService.order = Settings.data.wallpaper.wallhavenOrder; // Initialize resolution settings - var width = Settings.data.wallpaper.wallhavenResolutionWidth || "" - var height = Settings.data.wallpaper.wallhavenResolutionHeight || "" - var mode = Settings.data.wallpaper.wallhavenResolutionMode || "atleast" + var width = Settings.data.wallpaper.wallhavenResolutionWidth || ""; + var height = Settings.data.wallpaper.wallhavenResolutionHeight || ""; + var mode = Settings.data.wallpaper.wallhavenResolutionMode || "atleast"; if (width && height) { - var resolution = width + "x" + height + var resolution = width + "x" + height; if (mode === "atleast") { - WallhavenService.minResolution = resolution - WallhavenService.resolutions = "" + WallhavenService.minResolution = resolution; + WallhavenService.resolutions = ""; } else { - WallhavenService.minResolution = "" - WallhavenService.resolutions = resolution + WallhavenService.minResolution = ""; + WallhavenService.resolutions = resolution; } } else { - WallhavenService.minResolution = "" - WallhavenService.resolutions = "" + WallhavenService.minResolution = ""; + WallhavenService.resolutions = ""; } // Now check if we can actually search (fetching check is in WallhavenService.search) - loading = true - WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1) + loading = true; + WallhavenService.search(Settings.data.wallpaper.wallhavenQuery || "", 1); } } @@ -930,15 +933,15 @@ SmartPanel { onCurrentIndexChanged: { if (currentIndex >= 0) { - let row = Math.floor(currentIndex / columns) - let itemY = row * cellHeight - let viewportTop = contentY - let viewportBottom = viewportTop + height + let row = Math.floor(currentIndex / columns); + let itemY = row * cellHeight; + let viewportTop = contentY; + let viewportBottom = viewportTop + height; if (itemY < viewportTop) { - contentY = Math.max(0, itemY - cellHeight) + contentY = Math.max(0, itemY - cellHeight); } else if (itemY + cellHeight > viewportBottom) { - contentY = itemY + cellHeight - height + cellHeight + contentY = itemY + cellHeight - height + cellHeight; } } } @@ -946,10 +949,10 @@ SmartPanel { Keys.onPressed: event => { if (event.key === Qt.Key_Return || event.key === Qt.Key_Space) { if (currentIndex >= 0 && currentIndex < wallpapers.length) { - let wallpaper = wallpapers[currentIndex] - wallhavenDownloadAndApply(wallpaper) + let wallpaper = wallpapers[currentIndex]; + wallhavenDownloadAndApply(wallpaper); } - event.accepted = true + event.accepted = true; } } @@ -1054,8 +1057,8 @@ SmartPanel { TapHandler { onTapped: { - wallhavenGridView.currentIndex = index - wallhavenDownloadAndApply(modelData) + wallhavenGridView.currentIndex = index; + wallhavenDownloadAndApply(modelData); } } } @@ -1236,12 +1239,12 @@ SmartPanel { WallhavenService.downloadWallpaper(wallpaper, function (success, localPath) { if (success) { if (!Settings.data.wallpaper.setWallpaperOnAllMonitors && currentScreenIndex < Quickshell.screens.length) { - WallpaperService.changeWallpaper(localPath, Quickshell.screens[currentScreenIndex].name) + WallpaperService.changeWallpaper(localPath, Quickshell.screens[currentScreenIndex].name); } else { - WallpaperService.changeWallpaper(localPath, undefined) + WallpaperService.changeWallpaper(localPath, undefined); } } - }) + }); } } } diff --git a/Modules/Panels/WiFi/WiFiPanel.qml b/Modules/Panels/WiFi/WiFiPanel.qml index 178e010f..81a137b0 100644 --- a/Modules/Panels/WiFi/WiFiPanel.qml +++ b/Modules/Panels/WiFi/WiFiPanel.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import Quickshell import qs.Commons import qs.Modules.MainScreen @@ -206,14 +206,14 @@ SmartPanel { Repeater { model: { if (!Settings.data.network.wifiEnabled) - return [] + return []; - const nets = Object.values(NetworkService.networks) + const nets = Object.values(NetworkService.networks); return nets.sort((a, b) => { if (a.connected !== b.connected) - return b.connected - a.connected - return b.signal - a.signal - }) + return b.connected - a.connected; + return b.signal - a.signal; + }); } Rectangle { @@ -385,21 +385,21 @@ SmartPanel { visible: !modelData.connected && NetworkService.connectingTo !== modelData.ssid && passwordSsid !== modelData.ssid && NetworkService.forgettingNetwork !== modelData.ssid && NetworkService.disconnectingFrom !== modelData.ssid text: { if (modelData.existing || modelData.cached) - return I18n.tr("wifi.panel.connect") + return I18n.tr("wifi.panel.connect"); if (!NetworkService.isSecured(modelData.security)) - return I18n.tr("wifi.panel.connect") - return I18n.tr("wifi.panel.password") + return I18n.tr("wifi.panel.connect"); + return I18n.tr("wifi.panel.password"); } outlined: !hovered fontSize: Style.fontSizeXS enabled: !NetworkService.connecting onClicked: { if (modelData.existing || modelData.cached || !NetworkService.isSecured(modelData.security)) { - NetworkService.connect(modelData.ssid) + NetworkService.connect(modelData.ssid); } else { - passwordSsid = modelData.ssid - passwordInput = "" - expandedSsid = "" + passwordSsid = modelData.ssid; + passwordInput = ""; + expandedSsid = ""; } } } @@ -458,9 +458,9 @@ SmartPanel { forceActiveFocus() onAccepted: { if (text && !NetworkService.connecting) { - NetworkService.connect(passwordSsid, text) - passwordSsid = "" - passwordInput = "" + NetworkService.connect(passwordSsid, text); + passwordSsid = ""; + passwordInput = ""; } } @@ -480,9 +480,9 @@ SmartPanel { enabled: passwordInput.length > 0 && !NetworkService.connecting outlined: true onClicked: { - NetworkService.connect(passwordSsid, passwordInput) - passwordSsid = "" - passwordInput = "" + NetworkService.connect(passwordSsid, passwordInput); + passwordSsid = ""; + passwordInput = ""; } } @@ -490,8 +490,8 @@ SmartPanel { icon: "close" baseSize: Style.baseWidgetSize * 0.8 onClicked: { - passwordSsid = "" - passwordInput = "" + passwordSsid = ""; + passwordInput = ""; } } } @@ -535,8 +535,8 @@ SmartPanel { backgroundColor: Color.mError outlined: forgetButton.hovered ? false : true onClicked: { - NetworkService.forget(modelData.ssid) - expandedSsid = "" + NetworkService.forget(modelData.ssid); + expandedSsid = ""; } } diff --git a/Modules/Toast/SimpleToast.qml b/Modules/Toast/SimpleToast.qml index 9dbd62be..c2dcece2 100644 --- a/Modules/Toast/SimpleToast.qml +++ b/Modules/Toast/SimpleToast.qml @@ -35,11 +35,11 @@ Item { border.color: { switch (root.type) { case "warning": - return Color.mPrimary + return Color.mPrimary; case "error": - return Color.mError + return Color.mError; default: - return Color.mOutline + return Color.mOutline; } } } @@ -74,15 +74,15 @@ Item { id: hideAnimation interval: Style.animationFast onTriggered: { - root.visible = false - root.hidden() + root.visible = false; + root.hidden(); } } // Cleanup on destruction Component.onDestruction: { - hideTimer.stop() - hideAnimation.stop() + hideTimer.stop(); + hideAnimation.stop(); } RowLayout { @@ -97,22 +97,22 @@ Item { // Icon NIcon { icon: if (root.icon !== "") { - return root.icon + return root.icon; } else if (type === "warning") { - return "toast-warning" + return "toast-warning"; } else if (type === "error") { - return "toast-error" + return "toast-error"; } else { - return "toast-notice" + return "toast-notice"; } color: { switch (type) { case "warning": - return Color.mPrimary + return Color.mPrimary; case "error": - return Color.mError + return Color.mError; default: - return Color.mOnSurface + return Color.mOnSurface; } } pointSize: Style.fontSizeXXL * 1.5 @@ -156,35 +156,35 @@ Item { function show(msg, desc, msgIcon, msgType, msgDuration) { // Stop all timers first - hideTimer.stop() - hideAnimation.stop() + hideTimer.stop(); + hideAnimation.stop(); - message = msg - description = desc || "" - icon = msgIcon || "" - type = msgType || "notice" - duration = msgDuration || 3000 + message = msg; + description = desc || ""; + icon = msgIcon || ""; + type = msgType || "notice"; + duration = msgDuration || 3000; - visible = true - opacity = 1 - scale = 1.0 + visible = true; + opacity = 1; + scale = 1.0; - hideTimer.restart() + hideTimer.restart(); } function hide() { - hideTimer.stop() - opacity = 0 - scale = initialScale - hideAnimation.restart() + hideTimer.stop(); + opacity = 0; + scale = initialScale; + hideAnimation.restart(); } function hideImmediately() { - hideTimer.stop() - hideAnimation.stop() - opacity = 0 - scale = initialScale - root.visible = false - root.hidden() + hideTimer.stop(); + hideAnimation.stop(); + opacity = 0; + scale = initialScale; + root.visible = false; + root.hidden(); } } diff --git a/Modules/Toast/ToastScreen.qml b/Modules/Toast/ToastScreen.qml index e782a3ce..94880c6d 100644 --- a/Modules/Toast/ToastScreen.qml +++ b/Modules/Toast/ToastScreen.qml @@ -28,47 +28,47 @@ Item { "type": type, "duration": duration, "timestamp": Date.now() - }) + }); } } // Clear queue on component destruction to prevent orphaned toasts Component.onDestruction: { - messageQueue = [] - isShowingToast = false - hideTimer.stop() - quickSwitchTimer.stop() + messageQueue = []; + isShowingToast = false; + hideTimer.stop(); + quickSwitchTimer.stop(); } function enqueueToast(toastData) { // Safe logging - fix the substring bug - var descPreview = (toastData.description || "").substring(0, 100).replace(/\n/g, " ") - Logger.d("ToastScreen", "Queuing", toastData.type, ":", toastData.message, descPreview) + var descPreview = (toastData.description || "").substring(0, 100).replace(/\n/g, " "); + Logger.d("ToastScreen", "Queuing", toastData.type, ":", toastData.message, descPreview); // Bounded queue to prevent unbounded memory growth if (messageQueue.length >= maxQueueSize) { - Logger.d("ToastScreen", "Queue full, dropping oldest toast") - messageQueue.shift() + Logger.d("ToastScreen", "Queue full, dropping oldest toast"); + messageQueue.shift(); } if (replaceOnNew && isShowingToast) { // Cancel current toast and clear queue for latest toast - messageQueue = [] // Clear existing queue - messageQueue.push(toastData) + messageQueue = []; // Clear existing queue + messageQueue.push(toastData); // Hide current toast immediately if (windowLoader.item) { - hideTimer.stop() - windowLoader.item.hideToast() + hideTimer.stop(); + windowLoader.item.hideToast(); } // Process new toast after a brief delay - isShowingToast = false - quickSwitchTimer.restart() + isShowingToast = false; + quickSwitchTimer.restart(); } else { // Queue the toast - messageQueue.push(toastData) - processQueue() + messageQueue.push(toastData); + processQueue(); } } @@ -80,27 +80,27 @@ Item { function processQueue() { if (messageQueue.length === 0 || isShowingToast) { - return + return; } - var data = messageQueue.shift() - isShowingToast = true + var data = messageQueue.shift(); + isShowingToast = true; // Store the toast data for when loader is ready - windowLoader.pendingToast = data + windowLoader.pendingToast = data; // Activate the loader - onStatusChanged will handle showing the toast - windowLoader.active = true + windowLoader.active = true; } function onToastHidden() { - isShowingToast = false + isShowingToast = false; // Deactivate the loader to completely remove the window and free memory - windowLoader.active = false + windowLoader.active = false; // Small delay before processing next toast - hideTimer.restart() + hideTimer.restart(); } Timer { @@ -121,8 +121,8 @@ Item { onStatusChanged: { // When loader becomes ready, show the pending toast if (status === Loader.Ready && pendingToast !== null) { - item.showToast(pendingToast.message, pendingToast.description, pendingToast.icon, pendingToast.type, pendingToast.duration) - pendingToast = null + item.showToast(pendingToast.message, pendingToast.description, pendingToast.icon, pendingToast.type, pendingToast.duration); + pendingToast = null; } } @@ -147,30 +147,30 @@ Item { // Calculate bar offsets for each edge separately readonly property int barOffsetTop: { if (barPos !== "top") - return 0 - const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0 - return Style.barHeight + floatMarginV + return 0; + const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0; + return Style.barHeight + floatMarginV; } readonly property int barOffsetBottom: { if (barPos !== "bottom") - return 0 - const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0 - return Style.barHeight + floatMarginV + return 0; + const floatMarginV = isFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0; + return Style.barHeight + floatMarginV; } readonly property int barOffsetLeft: { if (barPos !== "left") - return 0 - const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0 - return floatMarginH + return 0; + const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0; + return floatMarginH; } readonly property int barOffsetRight: { if (barPos !== "right") - return 0 - const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0 - return floatMarginH + return 0; + const floatMarginH = isFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0; + return floatMarginH; } // Anchoring @@ -196,11 +196,11 @@ Item { //mask: Region {} function showToast(message, description, icon, type, duration) { - toastItem.show(message, description, icon, type, duration) + toastItem.show(message, description, icon, type, duration); } function hideToast() { - toastItem.hideImmediately() + toastItem.hideImmediately(); } SimpleToast { diff --git a/Modules/Tooltip/Tooltip.qml b/Modules/Tooltip/Tooltip.qml index e99ecff0..b982ff1f 100644 --- a/Modules/Tooltip/Tooltip.qml +++ b/Modules/Tooltip/Tooltip.qml @@ -42,7 +42,7 @@ PopupWindow { interval: root.delay repeat: false onTriggered: { - root.positionAndShow() + root.positionAndShow(); } } @@ -52,7 +52,7 @@ PopupWindow { interval: root.hideDelay repeat: false onTriggered: { - root.startHideAnimation() + root.startHideAnimation(); } } @@ -103,109 +103,113 @@ PopupWindow { } onFinished: { - root.completeHide() + root.completeHide(); } } // Function to show tooltip function show(screen, target, tipText, customDirection, showDelay, fontFamily) { if (!screen || !target || !tipText || tipText === "") - return + return; + root.screenWidth = screen.width; + root.screenHeight = screen.height; - root.screenWidth = screen.width - root.screenHeight = screen.height - - root.delay = showDelay + root.delay = showDelay; // Stop any running timers and animations - hideTimer.stop() - showTimer.stop() - hideAnimation.stop() - animatingOut = false + hideTimer.stop(); + showTimer.stop(); + hideAnimation.stop(); + animatingOut = false; // If we're already showing for a different target, hide immediately if (visible && targetItem !== target) { - hideImmediately() + hideImmediately(); } // Set properties - targetItem = target - text = tipText - pendingShow = true + targetItem = target; + text = tipText; + pendingShow = true; if (customDirection !== undefined) { - direction = customDirection + direction = customDirection; } else { - direction = "auto" + direction = "auto"; } - tooltipText.family = fontFamily ? fontFamily : Settings.data.ui.fontDefault + tooltipText.family = fontFamily ? fontFamily : Settings.data.ui.fontDefault; // Start show timer - showTimer.start() + showTimer.start(); } // Function to position and display the tooltip function positionAndShow() { if (!targetItem || !targetItem.parent || !pendingShow) { - return + return; } // Calculate tooltip dimensions - const tipWidth = Math.min(tooltipText.implicitWidth + (padding * 2), maxWidth) - root.implicitWidth = tipWidth + const tipWidth = Math.min(tooltipText.implicitWidth + (padding * 2), maxWidth); + root.implicitWidth = tipWidth; - const tipHeight = tooltipText.implicitHeight + (padding * 2) - root.implicitHeight = tipHeight + const tipHeight = tooltipText.implicitHeight + (padding * 2); + root.implicitHeight = tipHeight; // Get target's global position - var targetGlobal = targetItem.mapToItem(null, 0, 0) - const targetWidth = targetItem.width - const targetHeight = targetItem.height + var targetGlobal = targetItem.mapToItem(null, 0, 0); + const targetWidth = targetItem.width; + const targetHeight = targetItem.height; - var newAnchorX = 0 - var newAnchorY = 0 + var newAnchorX = 0; + var newAnchorY = 0; if (direction === "auto") { // Calculate available space in each direction - const spaceLeft = targetGlobal.x - const spaceRight = screenWidth - (targetGlobal.x + targetWidth) - const spaceTop = targetGlobal.y - const spaceBottom = screenHeight - (targetGlobal.y + targetHeight) + const spaceLeft = targetGlobal.x; + const spaceRight = screenWidth - (targetGlobal.x + targetWidth); + const spaceTop = targetGlobal.y; + const spaceBottom = screenHeight - (targetGlobal.y + targetHeight); // Try positions in order of available space - const positions = [{ - "dir": "bottom", - "space": spaceBottom, - "x": (targetWidth - tipWidth) / 2, - "y": targetHeight + margin, - "fits": spaceBottom >= tipHeight + margin - }, { - "dir": "top", - "space": spaceTop, - "x": (targetWidth - tipWidth) / 2, - "y": -tipHeight - margin, - "fits": spaceTop >= tipHeight + margin - }, { - "dir": "right", - "space": spaceRight, - "x": targetWidth + margin, - "y": (targetHeight - tipHeight) / 2, - "fits": spaceRight >= tipWidth + margin - }, { - "dir": "left", - "space": spaceLeft, - "x": -tipWidth - margin, - "y": (targetHeight - tipHeight) / 2, - "fits": spaceLeft >= tipWidth + margin - }] + const positions = [ + { + "dir": "bottom", + "space": spaceBottom, + "x": (targetWidth - tipWidth) / 2, + "y": targetHeight + margin, + "fits": spaceBottom >= tipHeight + margin + }, + { + "dir": "top", + "space": spaceTop, + "x": (targetWidth - tipWidth) / 2, + "y": -tipHeight - margin, + "fits": spaceTop >= tipHeight + margin + }, + { + "dir": "right", + "space": spaceRight, + "x": targetWidth + margin, + "y": (targetHeight - tipHeight) / 2, + "fits": spaceRight >= tipWidth + margin + }, + { + "dir": "left", + "space": spaceLeft, + "x": -tipWidth - margin, + "y": (targetHeight - tipHeight) / 2, + "fits": spaceLeft >= tipWidth + margin + } + ]; // Find first position that fits - var selectedPosition = null + var selectedPosition = null; for (var i = 0; i < positions.length; i++) { if (positions[i].fits) { - selectedPosition = positions[i] - break + selectedPosition = positions[i]; + break; } } @@ -213,171 +217,170 @@ PopupWindow { if (!selectedPosition) { // Sort by available space and use position with most space positions.sort(function (a, b) { - return b.space - a.space - }) - selectedPosition = positions[0] + return b.space - a.space; + }); + selectedPosition = positions[0]; } - newAnchorX = selectedPosition.x - newAnchorY = selectedPosition.y + newAnchorX = selectedPosition.x; + newAnchorY = selectedPosition.y; // Adjust horizontal position to keep tooltip on screen if (direction === "auto") { - const globalX = targetGlobal.x + newAnchorX + const globalX = targetGlobal.x + newAnchorX; if (globalX < 0) { - newAnchorX = -targetGlobal.x + margin + newAnchorX = -targetGlobal.x + margin; } else if (globalX + tipWidth > screenWidth) { - newAnchorX = screenWidth - targetGlobal.x - tipWidth - margin + newAnchorX = screenWidth - targetGlobal.x - tipWidth - margin; } } } else { // Manual direction positioning switch (direction) { case "left": - newAnchorX = -tipWidth - margin - newAnchorY = (targetHeight - tipHeight) / 2 - break + newAnchorX = -tipWidth - margin; + newAnchorY = (targetHeight - tipHeight) / 2; + break; case "right": - newAnchorX = targetWidth + margin - newAnchorY = (targetHeight - tipHeight) / 2 - break + newAnchorX = targetWidth + margin; + newAnchorY = (targetHeight - tipHeight) / 2; + break; case "top": - newAnchorX = (targetWidth - tipWidth) / 2 - newAnchorY = -tipHeight - margin - break + newAnchorX = (targetWidth - tipWidth) / 2; + newAnchorY = -tipHeight - margin; + break; case "bottom": - newAnchorX = (targetWidth - tipWidth) / 2 - newAnchorY = targetHeight + margin - break + newAnchorX = (targetWidth - tipWidth) / 2; + newAnchorY = targetHeight + margin; + break; } } // Apply position - anchorX = newAnchorX - anchorY = newAnchorY - isPositioned = true - pendingShow = false + anchorX = newAnchorX; + anchorY = newAnchorY; + isPositioned = true; + pendingShow = false; // Show tooltip and start animation - visible = true + visible = true; // Initialize animation state - tooltipContainer.opacity = 0.0 - tooltipContainer.scale = animationScale + tooltipContainer.opacity = 0.0; + tooltipContainer.scale = animationScale; // Start show animation - showAnimation.start() + showAnimation.start(); // Force anchor update after showing Qt.callLater(() => { if (root.anchor && root.visible) { - root.anchor.updateAnchor() + root.anchor.updateAnchor(); } - }) + }); } // Function to hide tooltip function hide() { // Stop show timer if it's running - showTimer.stop() - pendingShow = false + showTimer.stop(); + pendingShow = false; // Stop hide timer if it's running - hideTimer.stop() + hideTimer.stop(); if (hideDelay > 0 && visible && !animatingOut) { - hideTimer.start() + hideTimer.start(); } else { - startHideAnimation() + startHideAnimation(); } } function startHideAnimation() { if (!visible || animatingOut) - return - - animatingOut = true - showAnimation.stop() // Stop show animation if running - hideAnimation.start() + return; + animatingOut = true; + showAnimation.stop(); // Stop show animation if running + hideAnimation.start(); } function completeHide() { - visible = false - animatingOut = false - pendingShow = false - text = "" - isPositioned = false - tooltipContainer.opacity = 1.0 - tooltipContainer.scale = 1.0 + visible = false; + animatingOut = false; + pendingShow = false; + text = ""; + isPositioned = false; + tooltipContainer.opacity = 1.0; + tooltipContainer.scale = 1.0; } // Quick hide without delay or animation function hideImmediately() { - showTimer.stop() - hideTimer.stop() - showAnimation.stop() - hideAnimation.stop() - pendingShow = false - animatingOut = false - completeHide() + showTimer.stop(); + hideTimer.stop(); + showAnimation.stop(); + hideAnimation.stop(); + pendingShow = false; + animatingOut = false; + completeHide(); } // Update text function function updateText(newText) { if (visible && targetItem) { - text = newText + text = newText; // Recalculate dimensions - const tipWidth = Math.min(tooltipText.implicitWidth + (padding * 2), maxWidth) - root.implicitWidth = tipWidth + const tipWidth = Math.min(tooltipText.implicitWidth + (padding * 2), maxWidth); + root.implicitWidth = tipWidth; - const tipHeight = tooltipText.implicitHeight + (padding * 2) - root.implicitHeight = tipHeight + const tipHeight = tooltipText.implicitHeight + (padding * 2); + root.implicitHeight = tipHeight; // Reposition if necessary - var targetGlobal = targetItem.mapToItem(null, 0, 0) - const targetWidth = targetItem.width + var targetGlobal = targetItem.mapToItem(null, 0, 0); + const targetWidth = targetItem.width; // Adjust horizontal position to keep tooltip on screen if needed - const globalX = targetGlobal.x + anchorX + const globalX = targetGlobal.x + anchorX; if (globalX < 0) { - anchorX = -targetGlobal.x + margin + anchorX = -targetGlobal.x + margin; } else if (globalX + tipWidth > screenWidth) { - anchorX = screenWidth - targetGlobal.x - tipWidth - margin + anchorX = screenWidth - targetGlobal.x - tipWidth - margin; } // Force anchor update Qt.callLater(() => { if (root.anchor && root.visible) { - root.anchor.updateAnchor() + root.anchor.updateAnchor(); } - }) + }); } } // Reset function to clean up state function reset() { // Stop all timers and animations - showTimer.stop() - hideTimer.stop() - showAnimation.stop() - hideAnimation.stop() + showTimer.stop(); + hideTimer.stop(); + showAnimation.stop(); + hideAnimation.stop(); // Clear all state - visible = false - pendingShow = false - animatingOut = false - text = "" - isPositioned = false + visible = false; + pendingShow = false; + animatingOut = false; + text = ""; + isPositioned = false; // Reset to defaults - direction = "auto" - delay = 0 - hideDelay = 0 + direction = "auto"; + delay = 0; + hideDelay = 0; // Reset container state - tooltipContainer.opacity = 1.0 - tooltipContainer.scale = 1.0 + tooltipContainer.opacity = 1.0; + tooltipContainer.scale = 1.0; } // Tooltip content container for animations @@ -417,10 +420,10 @@ PopupWindow { } Component.onCompleted: { - reset() + reset(); } Component.onDestruction: { - reset() + reset(); } } diff --git a/Services/Compositor/CompositorService.qml b/Services/Compositor/CompositorService.qml index 3a890c05..51add9b3 100644 --- a/Services/Compositor/CompositorService.qml +++ b/Services/Compositor/CompositorService.qml @@ -39,62 +39,62 @@ Singleton { // Setup cache path (needs Settings to be available) Qt.callLater(() => { if (typeof Settings !== 'undefined' && Settings.cacheDir) { - displayCachePath = Settings.cacheDir + "display.json" - displayCacheFileView.path = displayCachePath + displayCachePath = Settings.cacheDir + "display.json"; + displayCacheFileView.path = displayCachePath; } - }) + }); - detectCompositor() + detectCompositor(); } function detectCompositor() { - const hyprlandSignature = Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE") - const niriSocket = Quickshell.env("NIRI_SOCKET") - const swaySock = Quickshell.env("SWAYSOCK") - const currentDesktop = Quickshell.env("XDG_CURRENT_DESKTOP") + const hyprlandSignature = Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE"); + const niriSocket = Quickshell.env("NIRI_SOCKET"); + const swaySock = Quickshell.env("SWAYSOCK"); + const currentDesktop = Quickshell.env("XDG_CURRENT_DESKTOP"); // Check for MangoWC using XDG_CURRENT_DESKTOP environment variable // MangoWC sets XDG_CURRENT_DESKTOP=mango if (currentDesktop && currentDesktop.toLowerCase().includes("mango")) { - isHyprland = false - isNiri = false - isSway = false - isMango = true - backendLoader.sourceComponent = mangoComponent + isHyprland = false; + isNiri = false; + isSway = false; + isMango = true; + backendLoader.sourceComponent = mangoComponent; } else if (niriSocket && niriSocket.length > 0) { - isHyprland = false - isNiri = true - isSway = false - isMango = false - backendLoader.sourceComponent = niriComponent + isHyprland = false; + isNiri = true; + isSway = false; + isMango = false; + backendLoader.sourceComponent = niriComponent; } else if (hyprlandSignature && hyprlandSignature.length > 0) { - isHyprland = true - isNiri = false - isSway = false - isMango = false - backendLoader.sourceComponent = hyprlandComponent + isHyprland = true; + isNiri = false; + isSway = false; + isMango = false; + backendLoader.sourceComponent = hyprlandComponent; } else if (swaySock && swaySock.length > 0) { - isHyprland = false - isNiri = false - isSway = true - isMango = false - backendLoader.sourceComponent = swayComponent + isHyprland = false; + isNiri = false; + isSway = true; + isMango = false; + backendLoader.sourceComponent = swayComponent; } else { // Always fallback to Niri - isHyprland = false - isNiri = true - isSway = false - isMango = false - backendLoader.sourceComponent = niriComponent + isHyprland = false; + isNiri = true; + isSway = false; + isMango = false; + backendLoader.sourceComponent = niriComponent; } } Loader { id: backendLoader onLoaded: { if (item) { - root.backend = item - setupBackendConnections() - backend.initialize() + root.backend = item; + setupBackendConnections(); + backend.initialize(); } } } @@ -112,14 +112,14 @@ Singleton { onLoaded: { // Load cached display scales - displayScales = displayCacheAdapter.displays || {} - displayScalesLoaded = true + displayScales = displayCacheAdapter.displays || {}; + displayScalesLoaded = true; // Logger.i("CompositorService", "Loaded display scales from cache:", JSON.stringify(displayScales)) } onLoadFailed: { // Cache doesn't exist yet, will be created on first update - displayScalesLoaded = true + displayScalesLoaded = true; // Logger.i("CompositorService", "No display cache found, will create on first update") } } @@ -158,227 +158,227 @@ Singleton { function setupBackendConnections() { if (!backend) - return + return; // Connect backend signals to facade signals backend.workspaceChanged.connect(() => { // Sync workspaces when they change - syncWorkspaces() + syncWorkspaces(); // Forward the signal - workspaceChanged() - }) + workspaceChanged(); + }); backend.activeWindowChanged.connect(() => { // Sync active window when it changes // TODO: Avoid re-syncing all windows - syncWindows() + syncWindows(); // Forward the signal - activeWindowChanged() - }) + activeWindowChanged(); + }); backend.windowListChanged.connect(() => { // Sync windows when they change - syncWindows() + syncWindows(); // Forward the signal - windowListChanged() - }) + windowListChanged(); + }); // Property bindings - use automatic property change signal backend.focusedWindowIndexChanged.connect(() => { - focusedWindowIndex = backend.focusedWindowIndex - }) + focusedWindowIndex = backend.focusedWindowIndex; + }); // Initial sync - syncWorkspaces() - syncWindows() - focusedWindowIndex = backend.focusedWindowIndex + syncWorkspaces(); + syncWindows(); + focusedWindowIndex = backend.focusedWindowIndex; } function syncWorkspaces() { - workspaces.clear() - const ws = backend.workspaces + workspaces.clear(); + const ws = backend.workspaces; for (var i = 0; i < ws.count; i++) { - workspaces.append(ws.get(i)) + workspaces.append(ws.get(i)); } // Emit signal to notify listeners that workspace list has been updated - workspacesChanged() + workspacesChanged(); } function syncWindows() { - windows.clear() - const ws = backend.windows + windows.clear(); + const ws = backend.windows; for (var i = 0; i < ws.length; i++) { - windows.append(ws[i]) + windows.append(ws[i]); } // Emit signal to notify listeners that workspace list has been updated - windowListChanged() + windowListChanged(); } // Update display scales from backend function updateDisplayScales() { if (!backend || !backend.queryDisplayScales) { - Logger.w("CompositorService", "Backend does not support display scale queries") - return + Logger.w("CompositorService", "Backend does not support display scale queries"); + return; } - backend.queryDisplayScales() + backend.queryDisplayScales(); } // Called by backend when display scales are ready function onDisplayScalesUpdated(scales) { - displayScales = scales - saveDisplayScalesToCache() - displayScalesChanged() - Logger.i("CompositorService", "Display scales updated") + displayScales = scales; + saveDisplayScalesToCache(); + displayScalesChanged(); + Logger.i("CompositorService", "Display scales updated"); } // Save display scales to cache function saveDisplayScalesToCache() { if (!displayCachePath) { - return + return; } - displayCacheAdapter.displays = displayScales - displayCacheFileView.writeAdapter() + displayCacheAdapter.displays = displayScales; + displayCacheFileView.writeAdapter(); } // Public function to get scale for a specific display function getDisplayScale(displayName) { if (!displayName || !displayScales[displayName]) { - return 1.0 + return 1.0; } - return displayScales[displayName].scale || 1.0 + return displayScales[displayName].scale || 1.0; } // Public function to get all display info for a specific display function getDisplayInfo(displayName) { if (!displayName || !displayScales[displayName]) { - return null + return null; } - return displayScales[displayName] + return displayScales[displayName]; } // Get focused window function getFocusedWindow() { if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { - return windows.get(focusedWindowIndex) + return windows.get(focusedWindowIndex); } - return null + return null; } // Get focused window title function getFocusedWindowTitle() { if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { - var title = windows.get(focusedWindowIndex).title + var title = windows.get(focusedWindowIndex).title; if (title !== undefined) { - title = title.replace(/(\r\n|\n|\r)/g, "") + title = title.replace(/(\r\n|\n|\r)/g, ""); } - return title || "" + return title || ""; } - return "" + return ""; } function getWindowsForWorkspace(workspaceId) { - var windowsInWs = [] + var windowsInWs = []; for (var i = 0; i < windows.count; i++) { - var window = windows.get(i) + var window = windows.get(i); if (window.workspaceId === workspaceId) { - windowsInWs.push(window) + windowsInWs.push(window); } } - return windowsInWs + return windowsInWs; } // Generic workspace switching function switchToWorkspace(workspace) { if (backend && backend.switchToWorkspace) { - backend.switchToWorkspace(workspace) + backend.switchToWorkspace(workspace); } else { - Logger.w("Compositor", "No backend available for workspace switching") + Logger.w("Compositor", "No backend available for workspace switching"); } } // Get current workspace function getCurrentWorkspace() { for (var i = 0; i < workspaces.count; i++) { - const ws = workspaces.get(i) + const ws = workspaces.get(i); if (ws.isFocused) { - return ws + return ws; } } - return null + return null; } // Get active workspaces function getActiveWorkspaces() { - const activeWorkspaces = [] + const activeWorkspaces = []; for (var i = 0; i < workspaces.count; i++) { - const ws = workspaces.get(i) + const ws = workspaces.get(i); if (ws.isActive) { - activeWorkspaces.push(ws) + activeWorkspaces.push(ws); } } - return activeWorkspaces + return activeWorkspaces; } // Set focused window function focusWindow(window) { if (backend && backend.focusWindow) { - backend.focusWindow(window) + backend.focusWindow(window); } else { - Logger.w("Compositor", "No backend available for window focus") + Logger.w("Compositor", "No backend available for window focus"); } } // Close window function closeWindow(window) { if (backend && backend.closeWindow) { - backend.closeWindow(window) + backend.closeWindow(window); } else { - Logger.w("Compositor", "No backend available for window closing") + Logger.w("Compositor", "No backend available for window closing"); } } // Session management function logout() { if (backend && backend.logout) { - Logger.i("Compositor", "Logout requested") - backend.logout() + Logger.i("Compositor", "Logout requested"); + backend.logout(); } else { - Logger.w("Compositor", "No backend available for logout") + Logger.w("Compositor", "No backend available for logout"); } } function shutdown() { - Logger.i("Compositor", "Shutdown requested") - Quickshell.execDetached(["sh", "-c", "systemctl poweroff || loginctl poweroff"]) + Logger.i("Compositor", "Shutdown requested"); + Quickshell.execDetached(["sh", "-c", "systemctl poweroff || loginctl poweroff"]); } function reboot() { - Logger.i("Compositor", "Reboot requested") - Quickshell.execDetached(["sh", "-c", "systemctl reboot || loginctl reboot"]) + Logger.i("Compositor", "Reboot requested"); + Quickshell.execDetached(["sh", "-c", "systemctl reboot || loginctl reboot"]); } function suspend() { - Logger.i("Compositor", "Suspend requested") - Quickshell.execDetached(["sh", "-c", "systemctl suspend || loginctl suspend"]) + Logger.i("Compositor", "Suspend requested"); + Quickshell.execDetached(["sh", "-c", "systemctl suspend || loginctl suspend"]); } function hibernate() { - Logger.i("Compositor", "Hibernate requested") - Quickshell.execDetached(["sh", "-c", "systemctl hibernate || loginctl hibernate"]) + Logger.i("Compositor", "Hibernate requested"); + Quickshell.execDetached(["sh", "-c", "systemctl hibernate || loginctl hibernate"]); } function lockAndSuspend() { - Logger.i("Compositor", "Lock and suspend requested") + Logger.i("Compositor", "Lock and suspend requested"); try { if (PanelService && PanelService.lockScreen && !PanelService.lockScreen.active) { - PanelService.lockScreen.active = true + PanelService.lockScreen.active = true; } } catch (e) { - Logger.w("Compositor", "Failed to activate lock screen before suspend: " + e) + Logger.w("Compositor", "Failed to activate lock screen before suspend: " + e); } // Queue suspend to the next event loop cycle to allow lock UI to render - Qt.callLater(suspend) + Qt.callLater(suspend); } } diff --git a/Services/Compositor/HyprlandService.qml b/Services/Compositor/HyprlandService.qml index f379c5a2..e3592321 100644 --- a/Services/Compositor/HyprlandService.qml +++ b/Services/Compositor/HyprlandService.qml @@ -35,27 +35,26 @@ Item { // Initialization function initialize() { if (initialized) - return - + return; try { - Hyprland.refreshWorkspaces() - Hyprland.refreshToplevels() + Hyprland.refreshWorkspaces(); + Hyprland.refreshToplevels(); Qt.callLater(() => { - safeUpdateWorkspaces() - safeUpdateWindows() - queryDisplayScales() - queryKeyboardLayout() - }) - initialized = true - Logger.i("HyprlandService", "Service started") + safeUpdateWorkspaces(); + safeUpdateWindows(); + queryDisplayScales(); + queryKeyboardLayout(); + }); + initialized = true; + Logger.i("HyprlandService", "Service started"); } catch (e) { - Logger.e("HyprlandService", "Failed to initialize:", e) + Logger.e("HyprlandService", "Failed to initialize:", e); } } // Query display scales function queryDisplayScales() { - hyprlandMonitorsProcess.running = true + hyprlandMonitorsProcess.running = true; } // Hyprland monitors process for display scale detection @@ -69,20 +68,20 @@ Item { stdout: SplitParser { onRead: function (line) { // Accumulate lines instead of parsing each one - hyprlandMonitorsProcess.accumulatedOutput += line + hyprlandMonitorsProcess.accumulatedOutput += line; } } onExited: function (exitCode) { if (exitCode !== 0 || !accumulatedOutput) { - Logger.e("HyprlandService", "Failed to query monitors, exit code:", exitCode) - accumulatedOutput = "" - return + Logger.e("HyprlandService", "Failed to query monitors, exit code:", exitCode); + accumulatedOutput = ""; + return; } try { - const monitorsData = JSON.parse(accumulatedOutput) - const scales = {} + const monitorsData = JSON.parse(accumulatedOutput); + const scales = {}; for (const monitor of monitorsData) { if (monitor.name) { @@ -97,25 +96,25 @@ Item { "active_workspace": monitor.activeWorkspace ? monitor.activeWorkspace.id : -1, "vrr": monitor.vrr || false, "focused": monitor.focused || false - } + }; } } // Notify CompositorService (it will emit displayScalesChanged) if (CompositorService && CompositorService.onDisplayScalesUpdated) { - CompositorService.onDisplayScalesUpdated(scales) + CompositorService.onDisplayScalesUpdated(scales); } } catch (e) { - Logger.e("HyprlandService", "Failed to parse monitors:", e) + Logger.e("HyprlandService", "Failed to parse monitors:", e); } finally { // Clear accumulated output for next query - accumulatedOutput = "" + accumulatedOutput = ""; } } } function queryKeyboardLayout() { - hyprlandDevicesProcess.running = true + hyprlandDevicesProcess.running = true; } // Hyprland devices process for keyboard layout detection Process { @@ -128,60 +127,59 @@ Item { stdout: SplitParser { onRead: function (line) { // Accumulate lines instead of parsing each one - hyprlandDevicesProcess.accumulatedOutput += line + hyprlandDevicesProcess.accumulatedOutput += line; } } onExited: function (exitCode) { if (exitCode !== 0 || !accumulatedOutput) { - Logger.e("HyprlandService", "Failed to query devices, exit code:", exitCode) - accumulatedOutput = "" - return + Logger.e("HyprlandService", "Failed to query devices, exit code:", exitCode); + accumulatedOutput = ""; + return; } try { - const devicesData = JSON.parse(accumulatedOutput) + const devicesData = JSON.parse(accumulatedOutput); for (const keyboard of devicesData.keyboards) { if (keyboard.main) { - const layoutName = keyboard.active_keymap - KeyboardLayoutService.setCurrentLayout(layoutName) - Logger.d("HyprlandService", "Keyboard layout switched:", layoutName) + const layoutName = keyboard.active_keymap; + KeyboardLayoutService.setCurrentLayout(layoutName); + Logger.d("HyprlandService", "Keyboard layout switched:", layoutName); } } } catch (e) { - Logger.e("HyprlandService", "Failed to parse devices:", e) + Logger.e("HyprlandService", "Failed to parse devices:", e); } finally { // Clear accumulated output for next query - accumulatedOutput = "" + accumulatedOutput = ""; } } } // Safe update wrapper function safeUpdate() { - safeUpdateWindows() - safeUpdateWorkspaces() - windowListChanged() + safeUpdateWindows(); + safeUpdateWorkspaces(); + windowListChanged(); } // Safe workspace update function safeUpdateWorkspaces() { try { - workspaces.clear() - workspaceCache = {} + workspaces.clear(); + workspaceCache = {}; if (!Hyprland.workspaces || !Hyprland.workspaces.values) { - return + return; } - const hlWorkspaces = Hyprland.workspaces.values - const occupiedIds = getOccupiedWorkspaceIds() + const hlWorkspaces = Hyprland.workspaces.values; + const occupiedIds = getOccupiedWorkspaceIds(); for (var i = 0; i < hlWorkspaces.length; i++) { - const ws = hlWorkspaces[i] + const ws = hlWorkspaces[i]; if (!ws || ws.id < 1) - continue - + continue; const wsData = { "id": ws.id, "idx": ws.id, @@ -191,107 +189,105 @@ Item { "isFocused": ws.focused === true, "isUrgent": ws.urgent === true, "isOccupied": occupiedIds[ws.id] === true - } + }; - workspaceCache[ws.id] = wsData - workspaces.append(wsData) + workspaceCache[ws.id] = wsData; + workspaces.append(wsData); } } catch (e) { - Logger.e("HyprlandService", "Error updating workspaces:", e) + Logger.e("HyprlandService", "Error updating workspaces:", e); } } // Get occupied workspace IDs safely function getOccupiedWorkspaceIds() { - const occupiedIds = {} + const occupiedIds = {}; try { if (!Hyprland.toplevels || !Hyprland.toplevels.values) { - return occupiedIds + return occupiedIds; } - const hlToplevels = Hyprland.toplevels.values + const hlToplevels = Hyprland.toplevels.values; for (var i = 0; i < hlToplevels.length; i++) { - const toplevel = hlToplevels[i] + const toplevel = hlToplevels[i]; if (!toplevel) - continue - + continue; try { - const wsId = toplevel.workspace ? toplevel.workspace.id : null + const wsId = toplevel.workspace ? toplevel.workspace.id : null; if (wsId !== null && wsId !== undefined) { - occupiedIds[wsId] = true + occupiedIds[wsId] = true; } - } catch (e) { + } catch (e) // Ignore individual toplevel errors - } + {} } - } catch (e) { + } catch (e) // Return empty if we can't determine occupancy - } + {} - return occupiedIds + return occupiedIds; } // Safe window update function safeUpdateWindows() { try { - const windowsList = [] - windowCache = {} + const windowsList = []; + windowCache = {}; if (!Hyprland.toplevels || !Hyprland.toplevels.values) { - windows = [] - focusedWindowIndex = -1 - return + windows = []; + focusedWindowIndex = -1; + return; } - const hlToplevels = Hyprland.toplevels.values - let newFocusedIndex = -1 + const hlToplevels = Hyprland.toplevels.values; + let newFocusedIndex = -1; for (var i = 0; i < hlToplevels.length; i++) { - const toplevel = hlToplevels[i] + const toplevel = hlToplevels[i]; if (!toplevel) - continue - - const windowData = extractWindowData(toplevel) + continue; + const windowData = extractWindowData(toplevel); if (windowData) { - windowsList.push(windowData) - windowCache[windowData.id] = windowData + windowsList.push(windowData); + windowCache[windowData.id] = windowData; if (windowData.isFocused) { - newFocusedIndex = windowsList.length - 1 + newFocusedIndex = windowsList.length - 1; } } } - windows = windowsList + windows = windowsList; if (newFocusedIndex !== focusedWindowIndex) { - focusedWindowIndex = newFocusedIndex - activeWindowChanged() + focusedWindowIndex = newFocusedIndex; + activeWindowChanged(); } } catch (e) { - Logger.e("HyprlandService", "Error updating windows:", e) + Logger.e("HyprlandService", "Error updating windows:", e); } } // Extract window data safely from a toplevel function extractWindowData(toplevel) { if (!toplevel) - return null + return null; try { // Safely extract properties - const windowId = safeGetProperty(toplevel, "address", "") + const windowId = safeGetProperty(toplevel, "address", ""); if (!windowId) - return null + return null; - const appId = getAppId(toplevel) - const title = getAppTitle(toplevel) - const wsId = toplevel.workspace ? toplevel.workspace.id : null - const focused = toplevel.activated === true - const output = toplevel.monitor?.name || "" + const appId = getAppId(toplevel); + const title = getAppTitle(toplevel); + const wsId = toplevel.workspace ? toplevel.workspace.id : null; + const focused = toplevel.activated === true; + const output = toplevel.monitor?.name || ""; return { "id": windowId, @@ -300,99 +296,93 @@ Item { "workspaceId": wsId || -1, "isFocused": focused, "output": output - } + }; } catch (e) { - return null + return null; } } function getAppTitle(toplevel) { try { - var title = toplevel.wayland.title + var title = toplevel.wayland.title; if (title) - return title - } catch (e) { + return title; + } catch (e) {} - } - - return safeGetProperty(toplevel, "title", "") + return safeGetProperty(toplevel, "title", ""); } function getAppId(toplevel) { if (!toplevel) - return "" + return ""; - var appId = "" + var appId = ""; // Try the wayland object first! // From my (Lemmy) testing it works fine so we could probably get rid of all the other attempts below. // Leaving them in for now, just in case... try { - appId = toplevel.wayland.appId + appId = toplevel.wayland.appId; if (appId) - return appId - } catch (e) { - - } + return appId; + } catch (e) {} // Try direct properties - appId = safeGetProperty(toplevel, "class", "") + appId = safeGetProperty(toplevel, "class", ""); if (appId) - return appId + return appId; - appId = safeGetProperty(toplevel, "initialClass", "") + appId = safeGetProperty(toplevel, "initialClass", ""); if (appId) - return appId + return appId; - appId = safeGetProperty(toplevel, "appId", "") + appId = safeGetProperty(toplevel, "appId", ""); if (appId) - return appId + return appId; // Try lastIpcObject try { - const ipcData = toplevel.lastIpcObject + const ipcData = toplevel.lastIpcObject; if (ipcData) { - return String(ipcData.class || ipcData.initialClass || ipcData.appId || ipcData.wm_class || "") + return String(ipcData.class || ipcData.initialClass || ipcData.appId || ipcData.wm_class || ""); } - } catch (e) { + } catch (e) {} - } - - return "" + return ""; } // Safe property getter function safeGetProperty(obj, prop, defaultValue) { try { - const value = obj[prop] + const value = obj[prop]; if (value !== undefined && value !== null) { - return String(value) + return String(value); } - } catch (e) { + } catch (e) // Property access failed - } - return defaultValue + {} + return defaultValue; } function handleActiveLayoutEvent(ev) { try { - let beforeParenthesis - const parenthesisPos = ev.lastIndexOf('(') + let beforeParenthesis; + const parenthesisPos = ev.lastIndexOf('('); if (parenthesisPos === -1) { - beforeParenthesis = ev + beforeParenthesis = ev; } else { - beforeParenthesis = ev.substring(0, parenthesisPos) + beforeParenthesis = ev.substring(0, parenthesisPos); } - const layoutNameStart = beforeParenthesis.lastIndexOf(',') + 1 - const layoutName = ev.substring(layoutNameStart) + const layoutNameStart = beforeParenthesis.lastIndexOf(',') + 1; + const layoutName = ev.substring(layoutNameStart); - KeyboardLayoutService.setCurrentLayout(layoutName) - Logger.d("HyprlandService", "Keyboard layout switched:", layoutName) + KeyboardLayoutService.setCurrentLayout(layoutName); + Logger.d("HyprlandService", "Keyboard layout switched:", layoutName); } catch (e) { - Logger.e("HyprlandService", "Error handling activelayout:", e) + Logger.e("HyprlandService", "Error handling activelayout:", e); } } @@ -401,8 +391,8 @@ Item { target: Hyprland.workspaces enabled: initialized function onValuesChanged() { - safeUpdateWorkspaces() - workspaceChanged() + safeUpdateWorkspaces(); + workspaceChanged(); } } @@ -410,7 +400,7 @@ Item { target: Hyprland.toplevels enabled: initialized function onValuesChanged() { - updateTimer.restart() + updateTimer.restart(); } } @@ -418,19 +408,19 @@ Item { target: Hyprland enabled: initialized function onRawEvent(event) { - Hyprland.refreshWorkspaces() - safeUpdateWorkspaces() - workspaceChanged() - updateTimer.restart() + Hyprland.refreshWorkspaces(); + safeUpdateWorkspaces(); + workspaceChanged(); + updateTimer.restart(); - const monitorsEvents = ["configreloaded", "monitoradded", "monitorremoved", "monitoraddedv2", "monitorremovedv2"] + const monitorsEvents = ["configreloaded", "monitoradded", "monitorremoved", "monitoraddedv2", "monitorremovedv2"]; if (monitorsEvents.includes(event.name)) { - Qt.callLater(queryDisplayScales) + Qt.callLater(queryDisplayScales); } if (event.name == "activelayout") { - handleActiveLayoutEvent(event.data) + handleActiveLayoutEvent(event.data); } } } @@ -438,33 +428,33 @@ Item { // Public functions function switchToWorkspace(workspace) { try { - Hyprland.dispatch(`workspace ${workspace.idx}`) + Hyprland.dispatch(`workspace ${workspace.idx}`); } catch (e) { - Logger.e("HyprlandService", "Failed to switch workspace:", e) + Logger.e("HyprlandService", "Failed to switch workspace:", e); } } function focusWindow(window) { try { - Hyprland.dispatch(`focuswindow address:0x${window.id.toString()}`) + Hyprland.dispatch(`focuswindow address:0x${window.id.toString()}`); } catch (e) { - Logger.e("HyprlandService", "Failed to switch window:", e) + Logger.e("HyprlandService", "Failed to switch window:", e); } } function closeWindow(window) { try { - Hyprland.dispatch(`killwindow address:0x${window.id}`) + Hyprland.dispatch(`killwindow address:0x${window.id}`); } catch (e) { - Logger.e("HyprlandService", "Failed to close window:", e) + Logger.e("HyprlandService", "Failed to close window:", e); } } function logout() { try { - Quickshell.execDetached(["hyprctl", "dispatch", "exit"]) + Quickshell.execDetached(["hyprctl", "dispatch", "exit"]); } catch (e) { - Logger.e("HyprlandService", "Failed to logout:", e) + Logger.e("HyprlandService", "Failed to logout:", e); } } } diff --git a/Services/Compositor/MangoService.qml b/Services/Compositor/MangoService.qml index d078a3e9..cb8aef42 100644 --- a/Services/Compositor/MangoService.qml +++ b/Services/Compositor/MangoService.qml @@ -2,8 +2,8 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Commons -import qs.Services.UI import qs.Services.Keyboard +import qs.Services.UI // MangoService integrates with MangoWC compositor using mmsg IPC commands // for real-time window management, workspace control, and state monitoring @@ -75,17 +75,17 @@ Item { stdout: SplitParser { onRead: function (line) { try { - handleEvent(line.trim()) + handleEvent(line.trim()); } catch (e) { - Logger.e("MangoService", "Event parsing error:", e, line) + Logger.e("MangoService", "Event parsing error:", e, line); } } } onExited: function (exitCode) { if (exitCode !== 0) { - Logger.e("MangoService", "Event stream exited, restarting...") - restartTimer.start() + Logger.e("MangoService", "Event stream exited, restarting..."); + restartTimer.start(); } } } @@ -96,7 +96,7 @@ Item { interval: 1000 onTriggered: { if (initialized) { - eventStream.running = true + eventStream.running = true; } } } @@ -110,17 +110,17 @@ Item { stdout: SplitParser { onRead: function (line) { - workspacesProcess.accumulatedOutput += line + "\n" + workspacesProcess.accumulatedOutput += line + "\n"; } } onExited: function (exitCode) { if (exitCode === 0) { - parseWorkspaces(accumulatedOutput) + parseWorkspaces(accumulatedOutput); } else { - Logger.e("MangoService", "Workspaces query failed:", exitCode) + Logger.e("MangoService", "Workspaces query failed:", exitCode); } - accumulatedOutput = "" + accumulatedOutput = ""; } } @@ -134,55 +134,54 @@ Item { onRunningChanged: { if (running) { - windowsProcess.currentWindow = {} + windowsProcess.currentWindow = {}; } } stdout: SplitParser { onRead: function (line) { - const trimmed = line.trim() + const trimmed = line.trim(); if (!trimmed) - return - - const parts = trimmed.split(' ') + return; + const parts = trimmed.split(' '); if (parts.length >= 3) { - const outputName = parts[0] - const property = parts[1] - const value = parts.slice(2).join(' ') + const outputName = parts[0]; + const property = parts[1]; + const value = parts.slice(2).join(' '); if (!windowsProcess.currentWindow[outputName]) { windowsProcess.currentWindow[outputName] = { "id": outputName, "output": outputName - } + }; } switch (property) { case "title": - windowsProcess.currentWindow[outputName].title = value - break + windowsProcess.currentWindow[outputName].title = value; + break; case "appid": - windowsProcess.currentWindow[outputName].appId = value - windowsProcess.currentWindow[outputName].class = value - break + windowsProcess.currentWindow[outputName].appId = value; + windowsProcess.currentWindow[outputName].class = value; + break; case "fullscreen": - windowsProcess.currentWindow[outputName].fullscreen = (value === "1") - break + windowsProcess.currentWindow[outputName].fullscreen = (value === "1"); + break; case "floating": - windowsProcess.currentWindow[outputName].floating = (value === "1") - break + windowsProcess.currentWindow[outputName].floating = (value === "1"); + break; case "x": - windowsProcess.currentWindow[outputName].x = parseInt(value) - break + windowsProcess.currentWindow[outputName].x = parseInt(value); + break; case "y": - windowsProcess.currentWindow[outputName].y = parseInt(value) - break + windowsProcess.currentWindow[outputName].y = parseInt(value); + break; case "width": - windowsProcess.currentWindow[outputName].width = parseInt(value) - break + windowsProcess.currentWindow[outputName].width = parseInt(value); + break; case "height": - windowsProcess.currentWindow[outputName].height = parseInt(value) - break + windowsProcess.currentWindow[outputName].height = parseInt(value); + break; } } } @@ -190,12 +189,12 @@ Item { onExited: function (exitCode) { if (exitCode === 0) { - parseWindows(windowsProcess.currentWindow) + parseWindows(windowsProcess.currentWindow); } else { - Logger.e("MangoService", "Windows query failed:", exitCode) + Logger.e("MangoService", "Windows query failed:", exitCode); } - accumulatedOutput = "" - windowsProcess.currentWindow = {} + accumulatedOutput = ""; + windowsProcess.currentWindow = {}; } } @@ -208,20 +207,20 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const parts = line.trim().split(/\s+/) + const parts = line.trim().split(/\s+/); if (parts.length >= 2) { - const layoutSymbol = parts.slice(1).join(' ') - handleLayoutChange(layoutSymbol) + const layoutSymbol = parts.slice(1).join(' '); + handleLayoutChange(layoutSymbol); } } catch (e) { - Logger.e("MangoService", "Layout parsing error:", e, line) + Logger.e("MangoService", "Layout parsing error:", e, line); } } } onExited: function (exitCode) { if (exitCode !== 0) { - Logger.e("MangoService", "Layout query failed:", exitCode) + Logger.e("MangoService", "Layout query failed:", exitCode); } } } @@ -235,23 +234,23 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const parts = line.trim().split(/\s+/) + const parts = line.trim().split(/\s+/); if (parts.length >= 2 && parts[1] === "kb_layout") { - const layoutName = parts.slice(2).join(' ') + const layoutName = parts.slice(2).join(' '); if (layoutName && layoutName !== currentKeyboardLayout) { - currentKeyboardLayout = layoutName - KeyboardLayoutService.setCurrentLayout(layoutName) + currentKeyboardLayout = layoutName; + KeyboardLayoutService.setCurrentLayout(layoutName); } } } catch (e) { - Logger.e("MangoService", "Keyboard layout parsing error:", e, line) + Logger.e("MangoService", "Keyboard layout parsing error:", e, line); } } } onExited: function (exitCode) { if (exitCode !== 0) { - Logger.e("MangoService", "Keyboard query failed:", exitCode) + Logger.e("MangoService", "Keyboard query failed:", exitCode); } } } @@ -265,29 +264,29 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const parts = line.trim().split(/\s+/) + const parts = line.trim().split(/\s+/); if (parts.length >= 3 && parts[1] === "scale_factor") { - const outputName = parts[0] - const scaleFactor = parseFloat(parts[2]) + const outputName = parts[0]; + const scaleFactor = parseFloat(parts[2]); if (!monitorCache[outputName]) { - monitorCache[outputName] = {} + monitorCache[outputName] = {}; } - monitorCache[outputName].scale = scaleFactor - monitorCache[outputName].name = outputName + monitorCache[outputName].scale = scaleFactor; + monitorCache[outputName].name = outputName; } } catch (e) { - Logger.e("MangoService", "Output parsing error:", e, line) + Logger.e("MangoService", "Output parsing error:", e, line); } } } onExited: function (exitCode) { if (exitCode === 0) { - updateDisplayScales() + updateDisplayScales(); } else { - Logger.e("MangoService", "Outputs query failed:", exitCode) + Logger.e("MangoService", "Outputs query failed:", exitCode); } } } @@ -301,24 +300,24 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const parts = line.trim().split(/\s+/) + const parts = line.trim().split(/\s+/); if (parts.length >= 3 && parts[1] === "selmon") { - const outputName = parts[0] - const isSelected = parts[2] === "1" + const outputName = parts[0]; + const isSelected = parts[2] === "1"; if (isSelected) { - selectedMonitor = outputName - Logger.d("MangoService", `Initial selected monitor: ${outputName}`) + selectedMonitor = outputName; + Logger.d("MangoService", `Initial selected monitor: ${outputName}`); } } } catch (e) { - Logger.e("MangoService", "Monitor state parsing error:", e, line) + Logger.e("MangoService", "Monitor state parsing error:", e, line); } } } onExited: function (exitCode) { if (exitCode !== 0) { - Logger.e("MangoService", "Monitor state query failed:", exitCode) + Logger.e("MangoService", "Monitor state query failed:", exitCode); } } } @@ -332,26 +331,26 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const trimmed = line.trim() + const trimmed = line.trim(); - const outputName = trimmed.replace(/^\+\s*/, '') + const outputName = trimmed.replace(/^\+\s*/, ''); if (outputName && !monitorCache[outputName]) { monitorCache[outputName] = { "name": outputName, "scale": 1.0, "active": false, "focused": false - } + }; } } catch (e) { - Logger.e("MangoService", "Output enumeration error:", e, line) + Logger.e("MangoService", "Output enumeration error:", e, line); } } } onExited: function (exitCode) { if (exitCode !== 0) { - Logger.e("MangoService", "Output enumeration failed:", exitCode) + Logger.e("MangoService", "Output enumeration failed:", exitCode); } } } @@ -359,46 +358,46 @@ Item { // Initialize MangoService and establish connection to MangoWC function initialize() { if (initialized) { - Logger.w("MangoService", "Already initialized") - return + Logger.w("MangoService", "Already initialized"); + return; } try { - Logger.i("MangoService", "Service started") + Logger.i("MangoService", "Service started"); - queryOutputEnum() - queryMonitorState() - eventStream.running = true - queryWorkspaces() - queryWindows() - queryLayout() - queryKeyboard() - queryOutputs() + queryOutputEnum(); + queryMonitorState(); + eventStream.running = true; + queryWorkspaces(); + queryWindows(); + queryLayout(); + queryKeyboard(); + queryOutputs(); - initialized = true - Logger.i("MangoService", "Service initialized successfully") + initialized = true; + Logger.i("MangoService", "Service initialized successfully"); } catch (e) { - Logger.e("MangoService", "Initialization failed:", e) - eventStream.running = true + Logger.e("MangoService", "Initialization failed:", e); + eventStream.running = true; } } // Switch to a specific workspace/tag function switchToWorkspace(workspace) { try { - const tagId = workspace.idx || workspace.id || defaultWorkspaceId - const outputName = workspace.output || selectedMonitor || "" - let command = mmsgCommands.action.tag.slice() + const tagId = workspace.idx || workspace.id || defaultWorkspaceId; + const outputName = workspace.output || selectedMonitor || ""; + let command = mmsgCommands.action.tag.slice(); // Only add -o parameter for multi-monitor setups if (outputName && Object.keys(monitorCache).length > 1) { - command.push("-o", outputName) + command.push("-o", outputName); } - command.push(tagId.toString()) + command.push(tagId.toString()); - Quickshell.execDetached(command) + Quickshell.execDetached(command); } catch (e) { - Logger.e("MangoService", "Failed to switch workspace:", e) + Logger.e("MangoService", "Failed to switch workspace:", e); } } @@ -406,67 +405,67 @@ Item { function focusWindow(window) { try { if (window && window.output) { - let command = mmsgCommands.action.view.slice() - const isMultiMonitor = Object.keys(monitorCache).length > 1 + let command = mmsgCommands.action.view.slice(); + const isMultiMonitor = Object.keys(monitorCache).length > 1; if (isMultiMonitor) { - command.push("-o", window.output) + command.push("-o", window.output); } - command.push(window.workspaceId.toString()) - Quickshell.execDetached(command) + command.push(window.workspaceId.toString()); + Quickshell.execDetached(command); Qt.callLater(() => { - let focusCommand = mmsgCommands.action.focusMaster.slice() + let focusCommand = mmsgCommands.action.focusMaster.slice(); if (isMultiMonitor) { - focusCommand.push("-o", window.output) + focusCommand.push("-o", window.output); } - Quickshell.execDetached(focusCommand) - }) + Quickshell.execDetached(focusCommand); + }); } } catch (e) { - Logger.e("MangoService", "Failed to focus window:", e) + Logger.e("MangoService", "Failed to focus window:", e); } } function closeWindow(window) { try { - const command = mmsgCommands.action.killClient.slice() + const command = mmsgCommands.action.killClient.slice(); if (selectedMonitor && Object.keys(monitorCache).length > 1) { - command.push("-o", selectedMonitor) + command.push("-o", selectedMonitor); } - Quickshell.execDetached(command) + Quickshell.execDetached(command); } catch (e) { - Logger.e("MangoService", "Failed to close window:", e) + Logger.e("MangoService", "Failed to close window:", e); } } function toggleOverview() { try { - const command = mmsgCommands.action.toggleOverview.slice() + const command = mmsgCommands.action.toggleOverview.slice(); if (selectedMonitor && Object.keys(monitorCache).length > 1) { - command.push("-o", selectedMonitor) + command.push("-o", selectedMonitor); } - Quickshell.execDetached(command) + Quickshell.execDetached(command); } catch (e) { - Logger.e("MangoService", "Failed to toggle overview:", e) + Logger.e("MangoService", "Failed to toggle overview:", e); } } function setLayout(layoutName) { try { - const command = mmsgCommands.action.setLayout.slice() - command.push(layoutName) - Quickshell.execDetached(command) + const command = mmsgCommands.action.setLayout.slice(); + command.push(layoutName); + Quickshell.execDetached(command); } catch (e) { - Logger.e("MangoService", "Failed to set layout:", e) + Logger.e("MangoService", "Failed to set layout:", e); } } function logout() { try { - Quickshell.execDetached(mmsgCommands.action.quit) + Quickshell.execDetached(mmsgCommands.action.quit); } catch (e) { - Logger.e("MangoService", "Failed to logout:", e) + Logger.e("MangoService", "Failed to logout:", e); } } @@ -474,32 +473,31 @@ Item { // Handles formats: tag details, tag masks, and binary states // State bits: bit 0 = active/selected, bit 1 = urgent function parseWorkspaces(output) { - const lines = output.trim().split('\n') - const workspacesList = [] - const newWorkspaceCache = {} - let outputClients = {} + const lines = output.trim().split('\n'); + const workspacesList = []; + const newWorkspaceCache = {}; + let outputClients = {}; for (const line of lines) { - const trimmed = line.trim() + const trimmed = line.trim(); if (!trimmed) - continue - - const tagMatch = trimmed.match(/^(\S+)\s+tag\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/) + continue; + const tagMatch = trimmed.match(/^(\S+)\s+tag\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/); if (tagMatch) { - const outputName = tagMatch[1] - const tagNum = tagMatch[2] - const state = tagMatch[3] - const clients = tagMatch[4] - const focused = tagMatch[5] - const tagId = parseInt(tagNum) + const outputName = tagMatch[1]; + const tagNum = tagMatch[2]; + const state = tagMatch[3]; + const clients = tagMatch[4]; + const focused = tagMatch[5]; + const tagId = parseInt(tagNum); - const isActive = (parseInt(state) & 1) !== 0 - const isUrgent = (parseInt(state) & 2) !== 0 - const isOccupied = parseInt(clients) > 0 - const isFocused = isActive && parseInt(focused) === 1 + const isActive = (parseInt(state) & 1) !== 0; + const isUrgent = (parseInt(state) & 2) !== 0; + const isOccupied = parseInt(clients) > 0; + const isFocused = isActive && parseInt(focused) === 1; if (!outputClients[outputName]) { - outputClients[outputName] = 0 + outputClients[outputName] = 0; } const workspaceData = { @@ -512,35 +510,35 @@ Item { "isUrgent": isUrgent, "isOccupied": isOccupied, "clients": parseInt(clients) - } + }; - newWorkspaceCache[`${outputName}-${tagId}`] = workspaceData - workspacesList.push(workspaceData) + newWorkspaceCache[`${outputName}-${tagId}`] = workspaceData; + workspacesList.push(workspaceData); } - const clientsMatch = trimmed.match(/^(\S+)\s+clients\s+(\d+)$/) + const clientsMatch = trimmed.match(/^(\S+)\s+clients\s+(\d+)$/); if (clientsMatch) { - const outputName = clientsMatch[1] - const clientCount = clientsMatch[2] - outputClients[outputName] = parseInt(clientCount) + const outputName = clientsMatch[1]; + const clientCount = clientsMatch[2]; + outputClients[outputName] = parseInt(clientCount); } - const tagsMatch = trimmed.match(/^(\S+)\s+tags\s+(\d+)\s+(\d+)\s+(\d+)$/) + const tagsMatch = trimmed.match(/^(\S+)\s+tags\s+(\d+)\s+(\d+)\s+(\d+)$/); if (tagsMatch) { - const outputName = tagsMatch[1] - const occ = tagsMatch[2] - const seltags = tagsMatch[3] - const urg = tagsMatch[4] + const outputName = tagsMatch[1]; + const occ = tagsMatch[2]; + const seltags = tagsMatch[3]; + const urg = tagsMatch[4]; - const occBits = occ.padStart(9, '0') - const selBits = seltags.padStart(9, '0') - const urgBits = urg.padStart(9, '0') + const occBits = occ.padStart(9, '0'); + const selBits = seltags.padStart(9, '0'); + const urgBits = urg.padStart(9, '0'); for (var i = 0; i < 9; i++) { - const tagId = i + 1 - const isActive = selBits[8 - i] === '1' - const isUrgent = urgBits[8 - i] === '1' - const isOccupied = occBits[8 - i] === '1' + const tagId = i + 1; + const isActive = selBits[8 - i] === '1'; + const isUrgent = urgBits[8 - i] === '1'; + const isOccupied = occBits[8 - i] === '1'; const workspaceData = { "id": tagId, @@ -553,63 +551,62 @@ Item { : isUrgent, "isOccupied": isOccupied, "clients": 0 // Will be updated by tag-specific data - } + }; - const key = `${outputName}-${tagId}` + const key = `${outputName}-${tagId}`; if (!newWorkspaceCache[key]) { - newWorkspaceCache[key] = workspaceData - workspacesList.push(workspaceData) + newWorkspaceCache[key] = workspaceData; + workspacesList.push(workspaceData); } } } - const layoutMatch = trimmed.match(/^(\S+)\s+layout\s+(\S+)$/) + const layoutMatch = trimmed.match(/^(\S+)\s+layout\s+(\S+)$/); if (layoutMatch) { - const layoutSymbol = layoutMatch[2] - handleLayoutChange(layoutSymbol) + const layoutSymbol = layoutMatch[2]; + handleLayoutChange(layoutSymbol); } } if (JSON.stringify(newWorkspaceCache) !== JSON.stringify(workspaceCache)) { - workspaceCache = newWorkspaceCache + workspaceCache = newWorkspaceCache; workspacesList.sort((a, b) => { if (a.id !== b.id) - return a.id - b.id - return a.output.localeCompare(b.output) - }) + return a.id - b.id; + return a.output.localeCompare(b.output); + }); - workspaces.clear() + workspaces.clear(); for (var i = 0; i < workspacesList.length; i++) { - workspaces.append(workspacesList[i]) + workspaces.append(workspacesList[i]); } - workspaceChanged() + workspaceChanged(); } } // Parse window data from mmsg -g -c output into window list function parseWindows(windowData) { - const windowsList = [] - const newWindowCache = {} - let newFocusedIndex = -1 + const windowsList = []; + const newWindowCache = {}; + let newFocusedIndex = -1; - const windowEntries = Object.entries(windowData) + const windowEntries = Object.entries(windowData); for (var i = 0; i < windowEntries.length; i++) { - const outputName = windowEntries[i][0] - const data = windowEntries[i][1] + const outputName = windowEntries[i][0]; + const data = windowEntries[i][1]; if (data.title || data.appId) { + const isFocused = (outputName === selectedMonitor); - const isFocused = (outputName === selectedMonitor) - - let activeTagId = defaultWorkspaceId - const workspaceEntries = Object.entries(workspaceCache) + let activeTagId = defaultWorkspaceId; + const workspaceEntries = Object.entries(workspaceCache); for (var j = 0; j < workspaceEntries.length; j++) { - const key = workspaceEntries[j][0] - const tagData = workspaceEntries[j][1] + const key = workspaceEntries[j][0]; + const tagData = workspaceEntries[j][1]; if (tagData.output === outputName && tagData.isActive) { - activeTagId = tagData.id - break + activeTagId = tagData.id; + break; } } @@ -633,54 +630,54 @@ Item { "width": data.width || 0, "height": data.height || 0 } - } + }; - windowsList.push(windowInfo) - newWindowCache[windowInfo.id] = windowInfo + windowsList.push(windowInfo); + newWindowCache[windowInfo.id] = windowInfo; if (isFocused) { - newFocusedIndex = windowsList.length - 1 - Logger.d("MangoService", `Focused window detected: ${data.title} on ${outputName}`) + newFocusedIndex = windowsList.length - 1; + Logger.d("MangoService", `Focused window detected: ${data.title} on ${outputName}`); } } } if (JSON.stringify(newWindowCache) !== JSON.stringify(windowCache)) { - windowCache = newWindowCache - windows = windowsList + windowCache = newWindowCache; + windows = windowsList; if (newFocusedIndex !== focusedWindowIndex) { - focusedWindowIndex = newFocusedIndex - activeWindowChanged() + focusedWindowIndex = newFocusedIndex; + activeWindowChanged(); } - windowListChanged() + windowListChanged(); } } // Handle layout change events and update overview state function handleLayoutChange(layoutSymbol) { - const wasOverview = overviewActive - const isOverview = (layoutSymbol === overviewLayoutSymbol) + const wasOverview = overviewActive; + const isOverview = (layoutSymbol === overviewLayoutSymbol); if (wasOverview !== isOverview) { - overviewActive = isOverview - Logger.d("MangoService", `Overview mode: ${overviewActive}`) + overviewActive = isOverview; + Logger.d("MangoService", `Overview mode: ${overviewActive}`); } if (layoutSymbol !== currentLayoutSymbol) { - currentLayoutSymbol = layoutSymbol - currentLayout = layoutSymbol + currentLayoutSymbol = layoutSymbol; + currentLayout = layoutSymbol; } } // Update display scales and notify CompositorService function updateDisplayScales() { - const scales = {} - const monitorEntries = Object.entries(monitorCache) + const scales = {}; + const monitorEntries = Object.entries(monitorCache); for (var i = 0; i < monitorEntries.length; i++) { - const outputName = monitorEntries[i][0] - const data = monitorEntries[i][1] + const outputName = monitorEntries[i][0]; + const data = monitorEntries[i][1]; scales[outputName] = { "name": data.name || outputName, "scale": data.scale || 1.0, @@ -691,35 +688,34 @@ Item { "y": data.y || 0, "active": data.active || false, "focused": data.focused || false - } + }; } if (CompositorService && CompositorService.onDisplayScalesUpdated) { - CompositorService.onDisplayScalesUpdated(scales) + CompositorService.onDisplayScalesUpdated(scales); } - displayScalesChanged() + displayScalesChanged(); } // Handle real-time events from mmsg -w event stream and trigger updates function handleEvent(eventLine) { - const parts = eventLine.trim().split(/\s+/) + const parts = eventLine.trim().split(/\s+/); if (parts.length < 2) - return - - const eventType = parts[1] + return; + const eventType = parts[1]; switch (eventType) { case "selmon": if (parts.length >= 3) { - const monitorName = parts[0] - const isSelected = parts[2] === "1" + const monitorName = parts[0]; + const isSelected = parts[2] === "1"; if (isSelected) { - selectedMonitor = monitorName - Logger.d("MangoService", `Selected monitor changed to: ${monitorName}`) + selectedMonitor = monitorName; + Logger.d("MangoService", `Selected monitor changed to: ${monitorName}`); } } - updateTimer.restart() - break + updateTimer.restart(); + break; case "tag": case "title": case "appid": @@ -733,81 +729,81 @@ Item { case "keymode": case "clients": case "tags": - updateTimer.restart() - break + updateTimer.restart(); + break; } } // Start workspace query process function queryWorkspaces() { - workspacesProcess.running = true + workspacesProcess.running = true; } // Start window query process function queryWindows() { - windowsProcess.running = true + windowsProcess.running = true; } // Start layout query process function queryLayout() { - layoutProcess.running = true + layoutProcess.running = true; } // Start keyboard layout query process function queryKeyboard() { - keyboardProcess.running = true + keyboardProcess.running = true; } // Start output scales query process function queryOutputs() { - outputsProcess.running = true + outputsProcess.running = true; } // Query display scales (alias for queryOutputs) function queryDisplayScales() { - queryOutputs() + queryOutputs(); } // Start output enumeration process function queryOutputEnum() { - outputEnumProcess.running = true + outputEnumProcess.running = true; } // Start monitor state query process function queryMonitorState() { - monitorStateProcess.running = true + monitorStateProcess.running = true; } // Safely update all state by querying workspaces, windows, and monitor state function safeUpdate() { try { - queryWorkspaces() - queryWindows() - queryMonitorState() + queryWorkspaces(); + queryWindows(); + queryMonitorState(); } catch (e) { - Logger.e("MangoService", "Safe update failed:", e) + Logger.e("MangoService", "Safe update failed:", e); } } // Get the ID of the currently active workspace/tag function getCurrentActiveTagId() { - const workspaceEntries1 = Object.entries(workspaceCache) + const workspaceEntries1 = Object.entries(workspaceCache); for (var i = 0; i < workspaceEntries1.length; i++) { - const key = workspaceEntries1[i][0] - const tagData = workspaceEntries1[i][1] + const key = workspaceEntries1[i][0]; + const tagData = workspaceEntries1[i][1]; if (tagData.isActive && tagData.output === selectedMonitor) { - return tagData.id + return tagData.id; } } - const workspaceEntries2 = Object.entries(workspaceCache) + const workspaceEntries2 = Object.entries(workspaceCache); for (var i = 0; i < workspaceEntries2.length; i++) { - const key = workspaceEntries2[i][0] - const tagData = workspaceEntries2[i][1] + const key = workspaceEntries2[i][0]; + const tagData = workspaceEntries2[i][1]; if (tagData.isActive) { - return tagData.id + return tagData.id; } } - return defaultWorkspaceId + return defaultWorkspaceId; } } diff --git a/Services/Compositor/NiriService.qml b/Services/Compositor/NiriService.qml index c7f0db11..27960aac 100644 --- a/Services/Compositor/NiriService.qml +++ b/Services/Compositor/NiriService.qml @@ -27,26 +27,26 @@ Item { // Initialization function initialize() { - niriEventStream.running = true - updateWorkspaces() - updateWindows() - queryDisplayScales() - Logger.i("NiriService", "Service started") + niriEventStream.running = true; + updateWorkspaces(); + updateWindows(); + queryDisplayScales(); + Logger.i("NiriService", "Service started"); } // Update workspaces function updateWorkspaces() { - niriWorkspaceProcess.running = true + niriWorkspaceProcess.running = true; } // Update windows function updateWindows() { - niriWindowsProcess.running = true + niriWindowsProcess.running = true; } // Query display scales function queryDisplayScales() { - niriOutputsProcess.running = true + niriOutputsProcess.running = true; } // Niri outputs process for display scale detection @@ -58,17 +58,17 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const outputsData = JSON.parse(line) - const scales = {} + const outputsData = JSON.parse(line); + const scales = {}; // Niri returns an object with display names as keys for (const outputName in outputsData) { - const output = outputsData[outputName] + const output = outputsData[outputName]; if (output && output.name) { - const logical = output.logical || {} - const currentModeIdx = output.current_mode || 0 - const modes = output.modes || [] - const currentMode = modes[currentModeIdx] || {} + const logical = output.logical || {}; + const currentModeIdx = output.current_mode || 0; + const modes = output.modes || []; + const currentMode = modes[currentModeIdx] || {}; scales[output.name] = { "name": output.name, @@ -83,16 +83,16 @@ Item { "vrr_supported": output.vrr_supported || false, "vrr_enabled": output.vrr_enabled || false, "transform": logical.transform || "Normal" - } + }; } } // Notify CompositorService (it will emit displayScalesChanged) if (CompositorService && CompositorService.onDisplayScalesUpdated) { - CompositorService.onDisplayScalesUpdated(scales) + CompositorService.onDisplayScalesUpdated(scales); } } catch (e) { - Logger.e("NiriService", "Failed to parse outputs:", e, line) + Logger.e("NiriService", "Failed to parse outputs:", e, line); } } } @@ -107,8 +107,8 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const workspacesData = JSON.parse(line) - const workspacesList = [] + const workspacesData = JSON.parse(line); + const workspacesList = []; for (const ws of workspacesData) { workspacesList.push({ @@ -120,26 +120,26 @@ Item { "isActive": ws.is_active === true, "isUrgent": ws.is_urgent === true, "isOccupied": ws.active_window_id ? true : false - }) + }); } // Sort workspaces by output, then by index workspacesList.sort((a, b) => { if (a.output !== b.output) { - return a.output.localeCompare(b.output) + return a.output.localeCompare(b.output); } - return a.idx - b.idx - }) + return a.idx - b.idx; + }); // Update the workspaces ListModel - workspaces.clear() + workspaces.clear(); for (var i = 0; i < workspacesList.length; i++) { - workspaces.append(workspacesList[i]) + workspaces.append(workspacesList[i]); } - workspaceChanged() + workspaceChanged(); } catch (e) { - Logger.e("NiriService", "Failed to parse workspaces:", e, line) + Logger.e("NiriService", "Failed to parse workspaces:", e, line); } } } @@ -154,10 +154,10 @@ Item { stdout: SplitParser { onRead: function (line) { try { - const windowsData = JSON.parse(line) - recollectWindows(windowsData) + const windowsData = JSON.parse(line); + recollectWindows(windowsData); } catch (e) { - Logger.e("NiriService", "Failed to parse windows:", e, line) + Logger.e("NiriService", "Failed to parse windows:", e, line); } } } @@ -172,35 +172,35 @@ Item { stdout: SplitParser { onRead: data => { try { - const event = JSON.parse(data.trim()) + const event = JSON.parse(data.trim()); if (event.WorkspacesChanged) { - updateWorkspaces() + updateWorkspaces(); } else if (event.WindowOpenedOrChanged) { - handleWindowOpenedOrChanged(event.WindowOpenedOrChanged) + handleWindowOpenedOrChanged(event.WindowOpenedOrChanged); } else if (event.WindowClosed) { - handleWindowClosed(event.WindowClosed) + handleWindowClosed(event.WindowClosed); } else if (event.WindowsChanged) { - handleWindowsChanged(event.WindowsChanged) + handleWindowsChanged(event.WindowsChanged); } else if (event.WorkspaceActivated) { - updateWorkspaces() + updateWorkspaces(); } else if (event.WindowFocusChanged) { - handleWindowFocusChanged(event.WindowFocusChanged) + handleWindowFocusChanged(event.WindowFocusChanged); } else if (event.WindowLayoutsChanged) { - handleWindowLayoutsChanged(event.WindowLayoutsChanged) + handleWindowLayoutsChanged(event.WindowLayoutsChanged); } else if (event.OverviewOpenedOrClosed) { - handleOverviewOpenedOrClosed(event.OverviewOpenedOrClosed) + handleOverviewOpenedOrClosed(event.OverviewOpenedOrClosed); } else if (event.OutputsChanged) { - queryDisplayScales() + queryDisplayScales(); } else if (event.ConfigLoaded) { - queryDisplayScales() + queryDisplayScales(); } else if (event.KeyboardLayoutsChanged) { - handleKeyboardLayoutsChanged(event.KeyboardLayoutsChanged) + handleKeyboardLayoutsChanged(event.KeyboardLayoutsChanged); } else if (event.KeyboardLayoutSwitched) { - handleKeyboardLayoutSwitched(event.KeyboardLayoutSwitched) + handleKeyboardLayoutSwitched(event.KeyboardLayoutSwitched); } } catch (e) { - Logger.e("NiriService", "Error parsing event stream:", e, data) + Logger.e("NiriService", "Error parsing event stream:", e, data); } } } @@ -212,22 +212,22 @@ Item { return { "x": layout.pos_in_scrolling_layout[0], "y": layout.pos_in_scrolling_layout[1] - } + }; } else { return { "x": floatingWindowPosition, "y": floatingWindowPosition - } + }; } } function getWindowOutput(win) { for (var i = 0; i < workspaces.count; i++) { if (workspaces.get(i).id === win.workspace_id) { - return workspaces.get(i).output + return workspaces.get(i).output; } } - return null + return null; } function getWindowData(win) { @@ -239,7 +239,7 @@ Item { "isFocused": win.is_focused === true, "output": getWindowOutput(win) || "", "position": getWindowPosition(win.layout) - } + }; } // Sort windows @@ -248,207 +248,207 @@ Item { // 3. by position Y function compareWindows(a, b) { if (a.workspaceId !== b.workspaceId) { - return a.workspaceId - b.workspaceId + return a.workspaceId - b.workspaceId; } if (a.position.x !== b.position.x) { - return a.position.x - b.position.x + return a.position.x - b.position.x; } - return a.position.y - b.position.y + return a.position.y - b.position.y; } function recollectWindows(windowsData) { - const windowsList = [] + const windowsList = []; for (const win of windowsData) { - windowsList.push(getWindowData(win)) + windowsList.push(getWindowData(win)); } - windowsList.sort(compareWindows) - windows = windowsList - windowListChanged() + windowsList.sort(compareWindows); + windows = windowsList; + windowListChanged(); - focusedWindowIndex = -1 + focusedWindowIndex = -1; for (var i = 0; i < windowsList.length; i++) { if (windowsList[i].isFocused) { - focusedWindowIndex = i - break + focusedWindowIndex = i; + break; } } - activeWindowChanged() + activeWindowChanged(); } // Event handlers function handleWindowOpenedOrChanged(eventData) { try { - const windowData = eventData.window - const existingIndex = windows.findIndex(w => w.id === windowData.id) - const newWindow = getWindowData(windowData) + const windowData = eventData.window; + const existingIndex = windows.findIndex(w => w.id === windowData.id); + const newWindow = getWindowData(windowData); if (existingIndex >= 0) { // Update existing window - windows[existingIndex] = newWindow + windows[existingIndex] = newWindow; } else { // Add new window - windows.push(newWindow) + windows.push(newWindow); } - windows.sort(compareWindows) + windows.sort(compareWindows); // Update focused window index if this window is focused if (newWindow.isFocused) { - const oldFocusedIndex = focusedWindowIndex - focusedWindowIndex = windows.findIndex(w => w.id === windowData.id) + const oldFocusedIndex = focusedWindowIndex; + focusedWindowIndex = windows.findIndex(w => w.id === windowData.id); // Only emit activeWindowChanged if the focused window actually changed if (oldFocusedIndex !== focusedWindowIndex) { if (oldFocusedIndex >= 0 && oldFocusedIndex < windows.length) { - windows[oldFocusedIndex].isFocused = false + windows[oldFocusedIndex].isFocused = false; } - activeWindowChanged() + activeWindowChanged(); } } - windowListChanged() + windowListChanged(); } catch (e) { - Logger.e("NiriService", "Error handling WindowOpenedOrChanged:", e) + Logger.e("NiriService", "Error handling WindowOpenedOrChanged:", e); } } function handleWindowClosed(eventData) { try { - const windowId = eventData.id - const windowIndex = windows.findIndex(w => w.id === windowId) + const windowId = eventData.id; + const windowIndex = windows.findIndex(w => w.id === windowId); if (windowIndex >= 0) { // If this was the focused window, clear focus if (windowIndex === focusedWindowIndex) { - focusedWindowIndex = -1 - activeWindowChanged() + focusedWindowIndex = -1; + activeWindowChanged(); } else if (focusedWindowIndex > windowIndex) { // Adjust focused window index if needed - focusedWindowIndex-- + focusedWindowIndex--; } // Remove the window - windows.splice(windowIndex, 1) - windowListChanged() + windows.splice(windowIndex, 1); + windowListChanged(); } } catch (e) { - Logger.e("NiriService", "Error handling WindowClosed:", e) + Logger.e("NiriService", "Error handling WindowClosed:", e); } } function handleWindowsChanged(eventData) { try { - const windowsData = eventData.windows - recollectWindows(windowsData) + const windowsData = eventData.windows; + recollectWindows(windowsData); } catch (e) { - Logger.e("NiriService", "Error handling WindowsChanged:", e) + Logger.e("NiriService", "Error handling WindowsChanged:", e); } } function handleWindowFocusChanged(eventData) { try { - const focusedId = eventData.id + const focusedId = eventData.id; if (windows[focusedWindowIndex]) { - windows[focusedWindowIndex].isFocused = false + windows[focusedWindowIndex].isFocused = false; } if (focusedId) { - const newIndex = windows.findIndex(w => w.id === focusedId) + const newIndex = windows.findIndex(w => w.id === focusedId); if (newIndex >= 0 && newIndex < windows.length) { - windows[newIndex].isFocused = true + windows[newIndex].isFocused = true; } - focusedWindowIndex = newIndex >= 0 ? newIndex : -1 + focusedWindowIndex = newIndex >= 0 ? newIndex : -1; } else { - focusedWindowIndex = -1 + focusedWindowIndex = -1; } - activeWindowChanged() + activeWindowChanged(); } catch (e) { - Logger.e("NiriService", "Error handling WindowFocusChanged:", e) + Logger.e("NiriService", "Error handling WindowFocusChanged:", e); } } function handleWindowLayoutsChanged(eventData) { try { for (const change of eventData.changes) { - const windowId = change[0] - const layout = change[1] - const window = windows.find(w => w.id === windowId) + const windowId = change[0]; + const layout = change[1]; + const window = windows.find(w => w.id === windowId); if (window) { - window.position = getWindowPosition(layout) + window.position = getWindowPosition(layout); } } - windows.sort(compareWindows) + windows.sort(compareWindows); - windowListChanged() + windowListChanged(); } catch (e) { - Logger.e("NiriService", "Error handling WindowLayoutChanged:", e) + Logger.e("NiriService", "Error handling WindowLayoutChanged:", e); } } function handleOverviewOpenedOrClosed(eventData) { try { - overviewActive = eventData.is_open - Logger.d("NiriService", "Overview opened or closed:", eventData.is_open) + overviewActive = eventData.is_open; + Logger.d("NiriService", "Overview opened or closed:", eventData.is_open); } catch (e) { - Logger.e("NiriService", "Error handling OverviewOpenedOrClosed:", e) + Logger.e("NiriService", "Error handling OverviewOpenedOrClosed:", e); } } function handleKeyboardLayoutsChanged(eventData) { try { - keyboardLayouts = eventData.keyboard_layouts.names - const layoutName = keyboardLayouts[eventData.keyboard_layouts.current_idx] - KeyboardLayoutService.setCurrentLayout(layoutName) - Logger.d("NiriService", "Keyboard layouts changed:", keyboardLayouts.toString()) + keyboardLayouts = eventData.keyboard_layouts.names; + const layoutName = keyboardLayouts[eventData.keyboard_layouts.current_idx]; + KeyboardLayoutService.setCurrentLayout(layoutName); + Logger.d("NiriService", "Keyboard layouts changed:", keyboardLayouts.toString()); } catch (e) { - Logger.e("NiriService", "Error handling keyboardLayoutsChanged:", e) + Logger.e("NiriService", "Error handling keyboardLayoutsChanged:", e); } } function handleKeyboardLayoutSwitched(eventData) { try { - const layoutName = keyboardLayouts[eventData.idx] - KeyboardLayoutService.setCurrentLayout(layoutName) - Logger.d("NiriService", "Keyboard layout switched:", layoutName) + const layoutName = keyboardLayouts[eventData.idx]; + KeyboardLayoutService.setCurrentLayout(layoutName); + Logger.d("NiriService", "Keyboard layout switched:", layoutName); } catch (e) { - Logger.e("NiriService", "Error handling KeyboardLayoutSwitched:", e) + Logger.e("NiriService", "Error handling KeyboardLayoutSwitched:", e); } } // Public functions function switchToWorkspace(workspace) { try { - Quickshell.execDetached(["niri", "msg", "action", "focus-workspace", workspace.idx.toString()]) + Quickshell.execDetached(["niri", "msg", "action", "focus-workspace", workspace.idx.toString()]); } catch (e) { - Logger.e("NiriService", "Failed to switch workspace:", e) + Logger.e("NiriService", "Failed to switch workspace:", e); } } function focusWindow(window) { try { - Quickshell.execDetached(["niri", "msg", "action", "focus-window", "--id", window.id.toString()]) + Quickshell.execDetached(["niri", "msg", "action", "focus-window", "--id", window.id.toString()]); } catch (e) { - Logger.e("NiriService", "Failed to switch window:", e) + Logger.e("NiriService", "Failed to switch window:", e); } } function closeWindow(window) { try { - Quickshell.execDetached(["niri", "msg", "action", "close-window", "--id", window.id.toString()]) + Quickshell.execDetached(["niri", "msg", "action", "close-window", "--id", window.id.toString()]); } catch (e) { - Logger.e("NiriService", "Failed to close window:", e) + Logger.e("NiriService", "Failed to close window:", e); } } function logout() { try { - Quickshell.execDetached(["niri", "msg", "action", "quit", "--skip-confirmation"]) + Quickshell.execDetached(["niri", "msg", "action", "quit", "--skip-confirmation"]); } catch (e) { - Logger.e("NiriService", "Failed to logout:", e) + Logger.e("NiriService", "Failed to logout:", e); } } } diff --git a/Services/Compositor/SwayService.qml b/Services/Compositor/SwayService.qml index 582c331f..32c49574 100644 --- a/Services/Compositor/SwayService.qml +++ b/Services/Compositor/SwayService.qml @@ -1,8 +1,8 @@ import QtQuick import Quickshell import Quickshell.I3 -import Quickshell.Wayland import Quickshell.Io +import Quickshell.Wayland import qs.Commons import qs.Services.Keyboard @@ -34,27 +34,26 @@ Item { // Initialization function initialize() { if (initialized) - return - + return; try { - I3.refreshWorkspaces() - I3.dispatch('(["input"])') + I3.refreshWorkspaces(); + I3.dispatch('(["input"])'); Qt.callLater(() => { - safeUpdateWorkspaces() - safeUpdateWindows() - queryDisplayScales() - queryKeyboardLayout() - }) - initialized = true - Logger.i("SwayService", "Service started") + safeUpdateWorkspaces(); + safeUpdateWindows(); + queryDisplayScales(); + queryKeyboardLayout(); + }); + initialized = true; + Logger.i("SwayService", "Service started"); } catch (e) { - Logger.e("SwayService", "Failed to initialize:", e) + Logger.e("SwayService", "Failed to initialize:", e); } } // Query display scales function queryDisplayScales() { - swayOutputsProcess.running = true + swayOutputsProcess.running = true; } // Sway outputs process for display scale detection @@ -67,20 +66,20 @@ Item { stdout: SplitParser { onRead: function (line) { - swayOutputsProcess.accumulatedOutput += line + swayOutputsProcess.accumulatedOutput += line; } } onExited: function (exitCode) { if (exitCode !== 0 || !accumulatedOutput) { - Logger.e("SwayService", "Failed to query outputs, exit code:", exitCode) - accumulatedOutput = "" - return + Logger.e("SwayService", "Failed to query outputs, exit code:", exitCode); + accumulatedOutput = ""; + return; } try { - const outputsData = JSON.parse(accumulatedOutput) - const scales = {} + const outputsData = JSON.parse(accumulatedOutput); + const scales = {}; for (const output of outputsData) { if (output.name) { @@ -95,19 +94,19 @@ Item { "active": output.active || false, "focused": output.focused || false, "current_workspace": output.current_workspace || "" - } + }; } } // Notify CompositorService (it will emit displayScalesChanged) if (CompositorService && CompositorService.onDisplayScalesUpdated) { - CompositorService.onDisplayScalesUpdated(scales) + CompositorService.onDisplayScalesUpdated(scales); } } catch (e) { - Logger.e("SwayService", "Failed to parse outputs:", e) + Logger.e("SwayService", "Failed to parse outputs:", e); } finally { // Clear accumulated output for next query - accumulatedOutput = "" + accumulatedOutput = ""; } } } @@ -118,12 +117,12 @@ Item { running: true repeat: true onTriggered: { - queryKeyboardLayout() + queryKeyboardLayout(); } } function queryKeyboardLayout() { - swayInputsProcess.running = true + swayInputsProcess.running = true; } // Sway inputs process for keyboard layout detection Process { @@ -136,59 +135,58 @@ Item { stdout: SplitParser { onRead: function (line) { // Accumulate lines instead of parsing each one - swayInputsProcess.accumulatedOutput += line + swayInputsProcess.accumulatedOutput += line; } } onExited: function (exitCode) { if (exitCode !== 0 || !accumulatedOutput) { - Logger.e("SwayService", "Failed to query inputs, exit code:", exitCode) - accumulatedOutput = "" - return + Logger.e("SwayService", "Failed to query inputs, exit code:", exitCode); + accumulatedOutput = ""; + return; } try { - const inputsData = JSON.parse(accumulatedOutput) + const inputsData = JSON.parse(accumulatedOutput); for (const input of inputsData) { if (input.type == "keyboard") { - const layoutName = input.xkb_active_layout_name - KeyboardLayoutService.setCurrentLayout(layoutName) - Logger.d("SwayService", "Keyboard layout switched:", layoutName) - break + const layoutName = input.xkb_active_layout_name; + KeyboardLayoutService.setCurrentLayout(layoutName); + Logger.d("SwayService", "Keyboard layout switched:", layoutName); + break; } } } catch (e) { - Logger.e("SwayService", "Failed to parse inputs:", e) + Logger.e("SwayService", "Failed to parse inputs:", e); } finally { // Clear accumulated output for next query - accumulatedOutput = "" + accumulatedOutput = ""; } } } // Safe update wrapper function safeUpdate() { - safeUpdateWindows() - safeUpdateWorkspaces() - windowListChanged() + safeUpdateWindows(); + safeUpdateWorkspaces(); + windowListChanged(); } // Safe workspace update function safeUpdateWorkspaces() { try { - workspaces.clear() + workspaces.clear(); if (!I3.workspaces || !I3.workspaces.values) { - return + return; } - const hlWorkspaces = I3.workspaces.values + const hlWorkspaces = I3.workspaces.values; for (var i = 0; i < hlWorkspaces.length; i++) { - const ws = hlWorkspaces[i] + const ws = hlWorkspaces[i]; if (!ws || ws.id < 1) - continue - + continue; const wsData = { "id": i, "idx": ws.num, @@ -199,116 +197,115 @@ Item { "isUrgent": ws.urgent === true, "isOccupied": true, "handle": ws - } + }; - workspaces.append(wsData) + workspaces.append(wsData); } } catch (e) { - Logger.e("SwayService", "Error updating workspaces:", e) + Logger.e("SwayService", "Error updating workspaces:", e); } } // Safe window update function safeUpdateWindows() { try { - const windowsList = [] + const windowsList = []; if (!ToplevelManager.toplevels || !ToplevelManager.toplevels.values) { - windows = [] - focusedWindowIndex = -1 - return + windows = []; + focusedWindowIndex = -1; + return; } - const hlToplevels = ToplevelManager.toplevels.values - let newFocusedIndex = -1 + const hlToplevels = ToplevelManager.toplevels.values; + let newFocusedIndex = -1; for (var i = 0; i < hlToplevels.length; i++) { - const toplevel = hlToplevels[i] + const toplevel = hlToplevels[i]; if (!toplevel) - continue - - const windowData = extractWindowData(toplevel) + continue; + const windowData = extractWindowData(toplevel); if (windowData) { - windowsList.push(windowData) + windowsList.push(windowData); if (windowData.isFocused) { - newFocusedIndex = windowsList.length - 1 + newFocusedIndex = windowsList.length - 1; } } } - windows = windowsList + windows = windowsList; if (newFocusedIndex !== focusedWindowIndex) { - focusedWindowIndex = newFocusedIndex - activeWindowChanged() + focusedWindowIndex = newFocusedIndex; + activeWindowChanged(); } } catch (e) { - Logger.e("SwayService", "Error updating windows:", e) + Logger.e("SwayService", "Error updating windows:", e); } } // Extract window data safely from a toplevel function extractWindowData(toplevel) { if (!toplevel) - return null + return null; try { // Safely extract properties - const appId = getAppId(toplevel) - const title = safeGetProperty(toplevel, "title", "") - const focused = toplevel.activated === true + const appId = getAppId(toplevel); + const title = safeGetProperty(toplevel, "title", ""); + const focused = toplevel.activated === true; return { "title": title, "appId": appId, "isFocused": focused, "handle": toplevel - } + }; } catch (e) { - return null + return null; } } function getAppId(toplevel) { if (!toplevel) - return "" + return ""; - return toplevel.appId + return toplevel.appId; } // Safe property getter function safeGetProperty(obj, prop, defaultValue) { try { - const value = obj[prop] + const value = obj[prop]; if (value !== undefined && value !== null) { - return String(value) + return String(value); } - } catch (e) { + } catch (e) // Property access failed - } - return defaultValue + {} + return defaultValue; } function handleInputEvent(ev) { try { - let beforeParenthesis - const parenthesisPos = ev.lastIndexOf('(') + let beforeParenthesis; + const parenthesisPos = ev.lastIndexOf('('); if (parenthesisPos === -1) { - beforeParenthesis = ev + beforeParenthesis = ev; } else { - beforeParenthesis = ev.substring(0, parenthesisPos) + beforeParenthesis = ev.substring(0, parenthesisPos); } - const layoutNameStart = beforeParenthesis.lastIndexOf(',') + 1 - const layoutName = ev.substring(layoutNameStart) + const layoutNameStart = beforeParenthesis.lastIndexOf(',') + 1; + const layoutName = ev.substring(layoutNameStart); - KeyboardLayoutService.setCurrentLayout(layoutName) - Logger.d("HyprlandService", "Keyboard layout switched:", layoutName) + KeyboardLayoutService.setCurrentLayout(layoutName); + Logger.d("HyprlandService", "Keyboard layout switched:", layoutName); } catch (e) { - Logger.e("HyprlandService", "Error handling activelayout:", e) + Logger.e("HyprlandService", "Error handling activelayout:", e); } } @@ -317,8 +314,8 @@ Item { target: I3.workspaces enabled: initialized function onValuesChanged() { - safeUpdateWorkspaces() - workspaceChanged() + safeUpdateWorkspaces(); + workspaceChanged(); } } @@ -326,7 +323,7 @@ Item { target: ToplevelManager enabled: initialized function onActiveToplevelChanged() { - updateTimer.restart() + updateTimer.restart(); } } @@ -334,16 +331,16 @@ Item { target: I3 enabled: initialized function onRawEvent(event) { - safeUpdateWorkspaces() - workspaceChanged() - updateTimer.restart() + safeUpdateWorkspaces(); + workspaceChanged(); + updateTimer.restart(); if (event.type === "output") { - Qt.callLater(queryDisplayScales) + Qt.callLater(queryDisplayScales); } if (event.type == "get_inputs") { - handleInputEvent(event.data) + handleInputEvent(event.data); } } } @@ -351,33 +348,33 @@ Item { // Public functions function switchToWorkspace(workspace) { try { - workspace.handle.activate() + workspace.handle.activate(); } catch (e) { - Logger.e("SwayService", "Failed to switch workspace:", e) + Logger.e("SwayService", "Failed to switch workspace:", e); } } function focusWindow(window) { try { - window.handle.activate() + window.handle.activate(); } catch (e) { - Logger.e("SwayService", "Failed to switch window:", e) + Logger.e("SwayService", "Failed to switch window:", e); } } function closeWindow(window) { try { - window.handle.close() + window.handle.close(); } catch (e) { - Logger.e("SwayService", "Failed to close window:", e) + Logger.e("SwayService", "Failed to close window:", e); } } function logout() { try { - Quickshell.execDetached(["swaymsg", "exit"]) + Quickshell.execDetached(["swaymsg", "exit"]); } catch (e) { - Logger.e("SwayService", "Failed to logout:", e) + Logger.e("SwayService", "Failed to logout:", e); } } } diff --git a/Services/Control/HooksService.qml b/Services/Control/HooksService.qml index 646cfbfd..9f227431 100644 --- a/Services/Control/HooksService.qml +++ b/Services/Control/HooksService.qml @@ -12,60 +12,60 @@ Singleton { Connections { target: Settings.data.colorSchemes function onDarkModeChanged() { - executeDarkModeHook(Settings.data.colorSchemes.darkMode) + executeDarkModeHook(Settings.data.colorSchemes.darkMode); } } Connections { target: WallpaperService function onWallpaperChanged(screenName, path) { - executeWallpaperHook(path, screenName) + executeWallpaperHook(path, screenName); } } // Execute wallpaper change hook function executeWallpaperHook(wallpaperPath, screenName) { if (!Settings.data.hooks?.enabled) { - return + return; } - const script = Settings.data.hooks?.wallpaperChange + const script = Settings.data.hooks?.wallpaperChange; if (!script || script === "") { - return + return; } try { - let command = script.replace(/\$1/g, wallpaperPath) - command = command.replace(/\$2/g, screenName || "") - Quickshell.execDetached(["sh", "-c", command]) - Logger.d("HooksService", `Executed wallpaper hook: ${command}`) + let command = script.replace(/\$1/g, wallpaperPath); + command = command.replace(/\$2/g, screenName || ""); + Quickshell.execDetached(["sh", "-c", command]); + Logger.d("HooksService", `Executed wallpaper hook: ${command}`); } catch (e) { - Logger.e("HooksService", `Failed to execute wallpaper hook: ${e}`) + Logger.e("HooksService", `Failed to execute wallpaper hook: ${e}`); } } // Execute dark mode change hook function executeDarkModeHook(isDarkMode) { if (!Settings.data.hooks?.enabled) { - return + return; } - const script = Settings.data.hooks?.darkModeChange + const script = Settings.data.hooks?.darkModeChange; if (!script || script === "") { - return + return; } try { - const command = script.replace(/\$1/g, isDarkMode ? "true" : "false") - Quickshell.execDetached(["sh", "-c", command]) - Logger.d("HooksService", `Executed dark mode hook: ${command}`) + const command = script.replace(/\$1/g, isDarkMode ? "true" : "false"); + Quickshell.execDetached(["sh", "-c", command]); + Logger.d("HooksService", `Executed dark mode hook: ${command}`); } catch (e) { - Logger.e("HooksService", `Failed to execute dark mode hook: ${e}`) + Logger.e("HooksService", `Failed to execute dark mode hook: ${e}`); } } // Initialize the service function init() { - Logger.i("HooksService", "Service started") + Logger.i("HooksService", "Service started"); } } diff --git a/Services/Control/IPCService.qml b/Services/Control/IPCService.qml index 660c97ad..ced678fc 100644 --- a/Services/Control/IPCService.qml +++ b/Services/Control/IPCService.qml @@ -19,7 +19,7 @@ Item { IpcHandler { target: "bar" function toggle() { - BarService.isVisible = !BarService.isVisible + BarService.isVisible = !BarService.isVisible; } } @@ -27,7 +27,7 @@ Item { target: "screenRecorder" function toggle() { if (ScreenRecorderService.isAvailable) { - ScreenRecorderService.toggleRecording() + ScreenRecorderService.toggleRecording(); } } } @@ -36,9 +36,9 @@ Item { target: "settings" function toggle() { root.withTargetScreen(screen => { - var settingsPanel = PanelService.getPanel("settingsPanel", screen) - settingsPanel?.toggle() - }) + var settingsPanel = PanelService.getPanel("settingsPanel", screen); + settingsPanel?.toggle(); + }); } } @@ -46,9 +46,9 @@ Item { target: "calendar" function toggle() { root.withTargetScreen(screen => { - var calendarPanel = PanelService.getPanel("calendarPanel", screen) - calendarPanel?.toggle(null, "Clock") - }) + var calendarPanel = PanelService.getPanel("calendarPanel", screen); + calendarPanel?.toggle(null, "Clock"); + }); } } @@ -57,36 +57,36 @@ Item { function toggleHistory() { // Will attempt to open the panel next to the bar button if any. root.withTargetScreen(screen => { - var notificationHistoryPanel = PanelService.getPanel("notificationHistoryPanel", screen) - notificationHistoryPanel.toggle(null, "NotificationHistory") - }) + var notificationHistoryPanel = PanelService.getPanel("notificationHistoryPanel", screen); + notificationHistoryPanel.toggle(null, "NotificationHistory"); + }); } function toggleDND() { - NotificationService.doNotDisturb = !NotificationService.doNotDisturb + NotificationService.doNotDisturb = !NotificationService.doNotDisturb; } function enableDND() { - NotificationService.doNotDisturb = true + NotificationService.doNotDisturb = true; } function disableDND() { - NotificationService.doNotDisturb = false + NotificationService.doNotDisturb = false; } function clear() { - NotificationService.clearHistory() + NotificationService.clearHistory(); } function dismissOldest() { - NotificationService.dismissOldestActive() + NotificationService.dismissOldestActive(); } function dismissAll() { - NotificationService.dismissAllActive() + NotificationService.dismissAllActive(); } } IpcHandler { target: "idleInhibitor" function toggle() { - return IdleInhibitorService.manualToggle() + return IdleInhibitorService.manualToggle(); } } @@ -94,23 +94,23 @@ Item { target: "launcher" function toggle() { root.withTargetScreen(screen => { - var launcherPanel = PanelService.getPanel("launcherPanel", screen) - launcherPanel?.toggle() - }) + var launcherPanel = PanelService.getPanel("launcherPanel", screen); + launcherPanel?.toggle(); + }); } function clipboard() { root.withTargetScreen(screen => { - var launcherPanel = PanelService.getPanel("launcherPanel", screen) - launcherPanel?.setSearchText(">clip ") - launcherPanel?.toggle() - }) + var launcherPanel = PanelService.getPanel("launcherPanel", screen); + launcherPanel?.setSearchText(">clip "); + launcherPanel?.toggle(); + }); } function calculator() { root.withTargetScreen(screen => { - var launcherPanel = PanelService.getPanel("launcherPanel", screen) - launcherPanel?.setSearchText(">calc ") - launcherPanel?.toggle() - }) + var launcherPanel = PanelService.getPanel("launcherPanel", screen); + launcherPanel?.setSearchText(">calc "); + launcherPanel?.toggle(); + }); } } @@ -122,22 +122,22 @@ Item { // Only lock if not already locked (prevents the red screen issue) // Note: No unlock via IPC for security reasons if (!lockScreen.active) { - lockScreen.triggeredViaDeprecatedCall = false - lockScreen.active = true + lockScreen.triggeredViaDeprecatedCall = false; + lockScreen.active = true; } } // Deprecated: Use 'lockScreen lock' instead function toggle() { // Mark as triggered via deprecated call - warning will show in lock screen - lockScreen.triggeredViaDeprecatedCall = true + lockScreen.triggeredViaDeprecatedCall = true; // Log deprecation warning for users checking logs - Logger.w("IPC", "The 'lockScreen toggle' IPC call is deprecated. Use 'lockScreen lock' instead.") + Logger.w("IPC", "The 'lockScreen toggle' IPC call is deprecated. Use 'lockScreen lock' instead."); // Still functional for backward compatibility if (!lockScreen.active) { - lockScreen.active = true + lockScreen.active = true; } } } @@ -145,52 +145,52 @@ Item { IpcHandler { target: "brightness" function increase() { - BrightnessService.increaseBrightness() + BrightnessService.increaseBrightness(); } function decrease() { - BrightnessService.decreaseBrightness() + BrightnessService.decreaseBrightness(); } } IpcHandler { target: "darkMode" function toggle() { - Settings.data.colorSchemes.darkMode = !Settings.data.colorSchemes.darkMode + Settings.data.colorSchemes.darkMode = !Settings.data.colorSchemes.darkMode; } function setDark() { - Settings.data.colorSchemes.darkMode = true + Settings.data.colorSchemes.darkMode = true; } function setLight() { - Settings.data.colorSchemes.darkMode = false + Settings.data.colorSchemes.darkMode = false; } } IpcHandler { target: "colorScheme" function set(schemeName: string) { - ColorSchemeService.setPredefinedScheme(schemeName) + ColorSchemeService.setPredefinedScheme(schemeName); } } IpcHandler { target: "volume" function increase() { - AudioService.increaseVolume() + AudioService.increaseVolume(); } function decrease() { - AudioService.decreaseVolume() + AudioService.decreaseVolume(); } function muteOutput() { - AudioService.setOutputMuted(!AudioService.muted) + AudioService.setOutputMuted(!AudioService.muted); } function increaseInput() { - AudioService.increaseInputVolume() + AudioService.increaseInputVolume(); } function decreaseInput() { - AudioService.decreaseInputVolume() + AudioService.decreaseInputVolume(); } function muteInput() { - AudioService.setInputMuted(!AudioService.inputMuted) + AudioService.setInputMuted(!AudioService.inputMuted); } } @@ -198,13 +198,13 @@ Item { target: "sessionMenu" function toggle() { root.withTargetScreen(screen => { - var sessionMenuPanel = PanelService.getPanel("sessionMenuPanel", screen) - sessionMenuPanel?.toggle() - }) + var sessionMenuPanel = PanelService.getPanel("sessionMenuPanel", screen); + sessionMenuPanel?.toggle(); + }); } function lockAndSuspend() { - CompositorService.lockAndSuspend() + CompositorService.lockAndSuspend(); } } @@ -212,14 +212,14 @@ Item { target: "controlCenter" function toggle() { root.withTargetScreen(screen => { - var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen) + var controlCenterPanel = PanelService.getPanel("controlCenterPanel", screen); if (Settings.data.controlCenter.position === "close_to_bar_button") { // Will attempt to open the panel next to the bar button if any. - controlCenterPanel?.toggle(null, "ControlCenter") + controlCenterPanel?.toggle(null, "ControlCenter"); } else { - controlCenterPanel?.toggle() + controlCenterPanel?.toggle(); } - }) + }); } } @@ -229,33 +229,33 @@ Item { function toggle() { if (Settings.data.wallpaper.enabled) { root.withTargetScreen(screen => { - var wallpaperPanel = PanelService.getPanel("wallpaperPanel", screen) - wallpaperPanel?.toggle() - }) + var wallpaperPanel = PanelService.getPanel("wallpaperPanel", screen); + wallpaperPanel?.toggle(); + }); } } function random() { if (Settings.data.wallpaper.enabled) { - WallpaperService.setRandomWallpaper() + WallpaperService.setRandomWallpaper(); } } function set(path: string, screen: string) { if (screen === "all" || screen === "") { - screen = undefined + screen = undefined; } - WallpaperService.changeWallpaper(path, screen) + WallpaperService.changeWallpaper(path, screen); } function toggleAutomation() { - Settings.data.wallpaper.randomEnabled = !Settings.data.wallpaper.randomEnabled + Settings.data.wallpaper.randomEnabled = !Settings.data.wallpaper.randomEnabled; } function disableAutomation() { - Settings.data.wallpaper.randomEnabled = false + Settings.data.wallpaper.randomEnabled = false; } function enableAutomation() { - Settings.data.wallpaper.randomEnabled = true + Settings.data.wallpaper.randomEnabled = true; } } @@ -263,20 +263,20 @@ Item { target: "batteryManager" function cycle() { - BatteryService.cycleModes() + BatteryService.cycleModes(); } function set(mode: string) { switch (mode) { case "full": - BatteryService.setChargingMode(BatteryService.ChargingMode.Full) - break + BatteryService.setChargingMode(BatteryService.ChargingMode.Full); + break; case "balanced": - BatteryService.setChargingMode(BatteryService.ChargingMode.Balanced) - break + BatteryService.setChargingMode(BatteryService.ChargingMode.Balanced); + break; case "lifespan": - BatteryService.setChargingMode(BatteryService.ChargingMode.Lifespan) - break + BatteryService.setChargingMode(BatteryService.ChargingMode.Lifespan); + break; } } } @@ -284,103 +284,102 @@ Item { IpcHandler { target: "powerProfile" function cycle() { - PowerProfileService.cycleProfile() + PowerProfileService.cycleProfile(); } function set(mode: string) { switch (mode) { case "performance": - PowerProfileService.setProfile(2) - break + PowerProfileService.setProfile(2); + break; case "balanced": - PowerProfileService.setProfile(1) - break + PowerProfileService.setProfile(1); + break; case "powersaver": - PowerProfileService.setProfile(0) - break + PowerProfileService.setProfile(0); + break; } } function toggleNoctaliaPerformance() { - PowerProfileService.toggleNoctaliaPerformance() + PowerProfileService.toggleNoctaliaPerformance(); } function enableNoctaliaPerformance() { - PowerProfileService.setNoctaliaPerformance(true) + PowerProfileService.setNoctaliaPerformance(true); } function disableNoctaliaPerformance() { - PowerProfileService.setNoctaliaPerformance(false) + PowerProfileService.setNoctaliaPerformance(false); } } IpcHandler { target: "media" function playPause() { - MediaService.playPause() + MediaService.playPause(); } function play() { - MediaService.play() + MediaService.play(); } function stop() { - MediaService.stop() + MediaService.stop(); } function pause() { - MediaService.pause() + MediaService.pause(); } function next() { - MediaService.next() + MediaService.next(); } function previous() { - MediaService.previous() + MediaService.previous(); } function seekRelative(offset: string) { - var offsetVal = parseFloat(offset) + var offsetVal = parseFloat(offset); if (Number.isNaN(offsetVal)) { - Logger.w("Media", "Argument to ipc call 'media seekRelative' must be a number") - return + Logger.w("Media", "Argument to ipc call 'media seekRelative' must be a number"); + return; } - MediaService.seekRelative(offsetVal) + MediaService.seekRelative(offsetVal); } function seekByRatio(position: string) { - var positionVal = parseFloat(position) + var positionVal = parseFloat(position); if (Number.isNaN(positionVal)) { - Logger.w("Media", "Argument to ipc call 'media seekByRatio' must be a number") - return + Logger.w("Media", "Argument to ipc call 'media seekByRatio' must be a number"); + return; } - MediaService.seekByRatio(positionVal) + MediaService.seekByRatio(positionVal); } } // Queue an IPC panel operation - will execute when screen is detected function withTargetScreen(callback) { if (pendingCallback) { - Logger.w("IPC", "Another IPC call is pending, ignoring new call") - return + Logger.w("IPC", "Another IPC call is pending, ignoring new call"); + return; } // Single monitor setup can execute immediately if (Quickshell.screens.length === 1) { - callback(Quickshell.screens[0]) + callback(Quickshell.screens[0]); } else { // Multi-monitors setup needs to start async detection - detectedScreen = null - pendingCallback = callback - screenDetectorLoader.active = true + detectedScreen = null; + pendingCallback = callback; + screenDetectorLoader.active = true; } } - /** - * For IPC calls on multi-monitors setup that will open panels on screen, - * we need to open a QS PanelWindow and wait for it's "screen" property to stabilize. + * For IPC calls on multi-monitors setup that will open panels on screen, + * we need to open a QS PanelWindow and wait for it's "screen" property to stabilize. */ property ShellScreen detectedScreen: null property var pendingCallback: null @@ -390,17 +389,17 @@ Item { running: false interval: 20 onTriggered: { - Logger.d("IPC", "Screen debounced to:", detectedScreen?.name || "null") + Logger.d("IPC", "Screen debounced to:", detectedScreen?.name || "null"); // Execute pending callback if any if (pendingCallback) { - Logger.d("IPC", "Executing pending IPC callback on screen:", detectedScreen.name) - pendingCallback(detectedScreen) - pendingCallback = null + Logger.d("IPC", "Executing pending IPC callback on screen:", detectedScreen.name); + pendingCallback(detectedScreen); + pendingCallback = null; } // Clean up - screenDetectorLoader.active = false + screenDetectorLoader.active = false; } } @@ -417,8 +416,8 @@ Item { mask: Region {} onScreenChanged: { - detectedScreen = screen - screenDetectorDebounce.restart() + detectedScreen = screen; + screenDetectorDebounce.restart(); } } } diff --git a/Services/Hardware/BatteryService.qml b/Services/Hardware/BatteryService.qml index a655be64..49f35d1c 100644 --- a/Services/Hardware/BatteryService.qml +++ b/Services/Hardware/BatteryService.qml @@ -9,239 +9,24 @@ import qs.Services.UI Singleton { id: root - enum ChargingMode { - Disabled = 0, - Full, - Balanced, - Lifespan - } - - property int chargingMode: Settings.data.battery.chargingMode - readonly property string batterySetterScript: Quickshell.shellDir + '/Bin/battery-manager/set-battery-treshold.sh' - readonly property string batteryInstallerScript: Quickshell.shellDir + '/Bin/battery-manager/install-battery-manager.sh' - readonly property string batteryUninstallerScript: Quickshell.shellDir + '/Bin/battery-manager/uninstall-battery-manager.sh' - - // This is used to omit toast message and writing mode to settings on startup - property bool initialSetter: true - // Choose icon based on charge and charging state function getIcon(percent, charging, isReady) { if (!isReady) { - return "battery-exclamation" + return "battery-exclamation"; } if (charging) { - return "battery-charging" + return "battery-charging"; } else { if (percent >= 90) - return "battery-4" + return "battery-4"; if (percent >= 50) - return "battery-3" + return "battery-3"; if (percent >= 25) - return "battery-2" + return "battery-2"; if (percent >= 0) - return "battery-1" - return "battery" - } - } - - function getThresholdValue(chargingMode) { - switch (chargingMode) { - case BatteryService.ChargingMode.Full: - return "100" - case BatteryService.ChargingMode.Balanced: - return "80" - case BatteryService.ChargingMode.Lifespan: - return "60" - } - } - - function toggleEnabled(enabled) { - if (enabled) { - setChargingMode(BatteryService.ChargingMode.Full) - } else { - BatteryService.initialSetter = true - ToastService.showNotice(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.uninstall-setup")) - PanelService.getPanel("batteryPanel", screen)?.toggle(this) - uninstallerProcess.running = true - } - } - - function setChargingMode(newMode) { - if (newMode !== BatteryService.ChargingMode.Full && newMode !== BatteryService.ChargingMode.Balanced && newMode !== BatteryService.ChargingMode.Lifespan) { - Logger.w("BatteryService", `Invalid charging mode set ${newMode}`) - return - } - BatteryService.chargingMode = newMode - BatteryService.applyChargingMode() - } - - function cycleModes() { - // Cycles charging modes from full to lifespan while skipping disabled - const nextMode = (chargingMode % 3) + 1 - setChargingMode(nextMode) - } - - function applyChargingMode() { - let command = [batterySetterScript] - - // Currently the script sends notifications by default but quickshell - // uses toast messages so the flag is passed to supress notifs - command.push("-q") - - command.push(BatteryService.getThresholdValue(BatteryService.chargingMode)) - - setterProcess.command = command - setterProcess.running = true - } - - function runInstaller() { - installerProcess.command = ["pkexec", batteryInstallerScript] - installerProcess.running = true - } - - function init() { - if (BatteryService.chargingMode !== BatteryService.ChargingMode.Disabled && BatteryService.chargingMode !== BatteryService.ChargingMode.Full) { - BatteryService.applyChargingMode() - } - } - - Process { - id: setterProcess - workingDirectory: Quickshell.shellDir - running: false - onExited: (exitCode, exitStatus) => { - if (exitCode === 0) { - Logger.i("BatteryService", "Battery threshold set successfully") - if (BatteryService.initialSetter) { - BatteryService.initialSetter = false - return - } - ToastService.showNotice(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.set-success-desc", { - "percent": BatteryService.getThresholdValue(BatteryService.chargingMode) - }), "battery") - Settings.data.battery.chargingMode = BatteryService.chargingMode - } else if (exitCode === 2) { - ToastService.showWarning(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.initial-setup")) - PanelService.getPanel("batteryPanel", null)?.toggle(this) - BatteryService.runInstaller() - } else { - ToastService.showError(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.set-failed")) - Logger.e("BatteryService", `Setter process failed with exit code: ${exitCode}`) - } - } - stderr: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.w("BatteryService", "SetterProcess stderr:", this.text) - } - } - } - stdout: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.i("BatteryService", "SetterProcess stdout:", this.text) - } - } - } - } - - // Installer process - installs battery manager components - Process { - id: installerProcess - workingDirectory: Quickshell.shellDir - running: false - onExited: (exitCode, exitStatus) => { - if (exitCode === 0) { - ToastService.showNotice(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.install-success")) - BatteryService.applyChargingMode() - } else if (exitCode === 2) { - ToastService.showError(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.install-missing")) - } else if (exitCode === 3) { - ToastService.showError(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.install-unsupported")) - } else { - ToastService.showError(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.install-failed")) - } - - if (exitCode !== 0) { - BatteryService.chargingMode = BatteryService.ChargingMode.Disabled - } - } - stderr: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.w("BatteryService", "InstallerProcess stderr:", this.text) - } - } - } - stdout: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.i("BatteryService", "InstallerProcess stdout:", this.text) - } - } - } - } - - Process { - id: uninstallerProcess - workingDirectory: Quickshell.shellDir - command: ["pkexec", batteryUninstallerScript] - running: false - onExited: (exitCode, exitStatus) => { - if (exitCode === 0) { - Logger.i("BatteryService", "Battery Manager uninstalled successfully") - ToastService.showNotice(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.uninstall-success")) - Settings.data.battery.chargingMode = BatteryService.chargingMode - BatteryService.chargingMode = BatteryService.ChargingMode.Disabled - cleanupProcess.running = true - } else { - ToastService.showError(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.uninstall-failed")) - Logger.e("BatteryService", `Uninstaller process failed with exit code: ${exitCode}`) - } - } - stderr: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.w("BatteryService", "UninstallerProcess stderr:", this.text) - } - } - } - stdout: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.i("BatteryService", "UninstallerProcess stdout:", this.text) - } - } - } - } - - // Cleanup process - deletes uninstaller after it sucessfull ; - Process { - id: cleanupProcess - workingDirectory: Quickshell.shellDir - command: ["rm", "-rf", batteryUninstallerScript] - running: false - onExited: (exitCode, exitStatus) => { - if (exitCode === 0) { - Logger.i("BatteryService", "Battery Manager uninstalled successfully") - } else { - Logger.e("BatteryService", `Cleanup process failed with exit code: ${exitCode}`) - } - } - stderr: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.w("BatteryService", "CleanupProcess stderr:", this.text) - } - } - } - stdout: StdioCollector { - onStreamFinished: { - if (this.text) { - Logger.i("BatteryService", "CleanupProcess stdout:", this.text) - } - } + return "battery-1"; + return "battery"; } } } diff --git a/Services/Hardware/BrightnessService.qml b/Services/Hardware/BrightnessService.qml index f47d9168..822f03d2 100644 --- a/Services/Hardware/BrightnessService.qml +++ b/Services/Hardware/BrightnessService.qml @@ -13,49 +13,49 @@ Singleton { property bool appleDisplayPresent: false function getMonitorForScreen(screen: ShellScreen): var { - return monitors.find(m => m.modelData === screen) + return monitors.find(m => m.modelData === screen); } // Signal emitted when a specific monitor's brightness changes, includes monitor context signal monitorBrightnessChanged(var monitor, real newBrightness) function getAvailableMethods(): list { - var methods = [] + var methods = []; if (Settings.data.brightness.enableDdcSupport && monitors.some(m => m.isDdc)) - methods.push("ddcutil") + methods.push("ddcutil"); if (monitors.some(m => !m.isDdc)) - methods.push("internal") + methods.push("internal"); if (appleDisplayPresent) - methods.push("apple") - return methods + methods.push("apple"); + return methods; } // Global helpers for IPC and shortcuts function increaseBrightness(): void { - monitors.forEach(m => m.increaseBrightness()) + monitors.forEach(m => m.increaseBrightness()); } function decreaseBrightness(): void { - monitors.forEach(m => m.decreaseBrightness()) + monitors.forEach(m => m.decreaseBrightness()); } function getDetectedDisplays(): list { - return detectedDisplays + return detectedDisplays; } reloadableId: "brightness" Component.onCompleted: { - Logger.i("Brightness", "Service started") + Logger.i("Brightness", "Service started"); if (Settings.data.brightness.enableDdcSupport) { - ddcProc.running = true + ddcProc.running = true; } } onMonitorsChanged: { - ddcMonitors = [] + ddcMonitors = []; if (Settings.data.brightness.enableDdcSupport) { - ddcProc.running = true + ddcProc.running = true; } } @@ -64,11 +64,11 @@ Singleton { function onEnableDdcSupportChanged() { if (Settings.data.brightness.enableDdcSupport) { // Re-detect DDC monitors when enabled - ddcMonitors = [] - ddcProc.running = true + ddcMonitors = []; + ddcProc.running = true; } else { // Clear DDC monitors when disabled - ddcMonitors = [] + ddcMonitors = []; } } } @@ -95,23 +95,22 @@ Singleton { command: ["ddcutil", "detect", "--sleep-multiplier=0.5"] stdout: StdioCollector { onStreamFinished: { - var displays = text.trim().split("\n\n") + var displays = text.trim().split("\n\n"); ddcProc.ddcMonitors = displays.map(d => { - - var ddcModelMatch = d.match(/(This monitor does not support DDC\/CI|Invalid display)/) - var modelMatch = d.match(/Model:\s*(.*)/) - var busMatch = d.match(/I2C bus:[ ]*\/dev\/i2c-([0-9]+)/) - var ddcModel = ddcModelMatch ? ddcModelMatch.length > 0 : false - var model = modelMatch ? modelMatch[1] : "Unknown" - var bus = busMatch ? busMatch[1] : "Unknown" - Logger.i("Brigthness", "Detected DDC Monitor:", model, "on bus", bus, "is DDC:", !ddcModel) + var ddcModelMatch = d.match(/(This monitor does not support DDC\/CI|Invalid display)/); + var modelMatch = d.match(/Model:\s*(.*)/); + var busMatch = d.match(/I2C bus:[ ]*\/dev\/i2c-([0-9]+)/); + var ddcModel = ddcModelMatch ? ddcModelMatch.length > 0 : false; + var model = modelMatch ? modelMatch[1] : "Unknown"; + var bus = busMatch ? busMatch[1] : "Unknown"; + Logger.i("Brigthness", "Detected DDC Monitor:", model, "on bus", bus, "is DDC:", !ddcModel); return { "model": model, "busNum": bus, "isDdc": !ddcModel - } - }) - root.ddcMonitors = ddcProc.ddcMonitors.filter(m => m.isDdc) + }; + }); + root.ddcMonitors = ddcProc.ddcMonitors.filter(m => m.isDdc); } } } @@ -128,11 +127,11 @@ Singleton { // Check if brightness control is available for this monitor readonly property bool brightnessControlAvailable: { if (isAppleDisplay) - return true + return true; if (isDdc) - return true + return true; // For internal displays, check if we have a brightness path - return brightnessPath !== "" + return brightnessPath !== ""; } property real brightness @@ -153,23 +152,23 @@ Singleton { readonly property Process refreshProc: Process { stdout: StdioCollector { onStreamFinished: { - var dataText = text.trim() + var dataText = text.trim(); if (dataText === "") { - return + return; } - var lines = dataText.split("\n") + var lines = dataText.split("\n"); if (lines.length >= 2) { - var current = parseInt(lines[0].trim()) - var max = parseInt(lines[1].trim()) + var current = parseInt(lines[0].trim()); + var max = parseInt(lines[1].trim()); if (!isNaN(current) && !isNaN(max) && max > 0) { - var newBrightness = current / max + var newBrightness = current / max; // Only update if it's actually different (avoid feedback loops) if (Math.abs(newBrightness - monitor.brightness) > 0.01) { // Update internal value to match system state - monitor.brightness = newBrightness - monitor.brightnessUpdated(monitor.brightness) - root.monitorBrightnessChanged(monitor, monitor.brightness) + monitor.brightness = newBrightness; + monitor.brightnessUpdated(monitor.brightness); + root.monitorBrightnessChanged(monitor, monitor.brightness); //Logger.i("Brightness", "Refreshed brightness from system:", monitor.modelData.name, monitor.brightness) } } @@ -182,16 +181,16 @@ Singleton { function refreshBrightnessFromSystem() { if (!monitor.isDdc && !monitor.isAppleDisplay) { // For internal displays, query the system directly - refreshProc.command = ["sh", "-c", "cat " + monitor.brightnessPath + " && " + "cat " + monitor.maxBrightnessPath] - refreshProc.running = true + refreshProc.command = ["sh", "-c", "cat " + monitor.brightnessPath + " && " + "cat " + monitor.maxBrightnessPath]; + refreshProc.running = true; } else if (monitor.isDdc) { // For DDC displays, get the current value - refreshProc.command = ["ddcutil", "-b", monitor.busNum, "getvcp", "10", "--brief"] - refreshProc.running = true + refreshProc.command = ["ddcutil", "-b", monitor.busNum, "getvcp", "10", "--brief"]; + refreshProc.running = true; } else if (monitor.isAppleDisplay) { // For Apple displays, get the current value - refreshProc.command = ["asdbctl", "get"] - refreshProc.running = true + refreshProc.command = ["asdbctl", "get"]; + refreshProc.running = true; } } @@ -205,8 +204,8 @@ Singleton { // When a file change is detected, actively refresh from system // to ensure we get the most up-to-date value Qt.callLater(() => { - monitor.refreshBrightnessFromSystem() - }) + monitor.refreshBrightnessFromSystem(); + }); } } @@ -214,50 +213,50 @@ Singleton { readonly property Process initProc: Process { stdout: StdioCollector { onStreamFinished: { - var dataText = text.trim() + var dataText = text.trim(); if (dataText === "") { - return + return; } //Logger.i("Brightness", "Raw brightness data for", monitor.modelData.name + ":", dataText) if (monitor.isAppleDisplay) { - var val = parseInt(dataText) + var val = parseInt(dataText); if (!isNaN(val)) { - monitor.brightness = val / 101 - Logger.d("Brightness", "Apple display brightness:", monitor.brightness) + monitor.brightness = val / 101; + Logger.d("Brightness", "Apple display brightness:", monitor.brightness); } } else if (monitor.isDdc) { - var parts = dataText.split(" ") + var parts = dataText.split(" "); if (parts.length >= 4) { - var current = parseInt(parts[3]) - var max = parseInt(parts[4]) + var current = parseInt(parts[3]); + var max = parseInt(parts[4]); if (!isNaN(current) && !isNaN(max) && max > 0) { - monitor.brightness = current / max - Logger.d("Brightness", "DDC brightness:", current + "/" + max + " =", monitor.brightness) + monitor.brightness = current / max; + Logger.d("Brightness", "DDC brightness:", current + "/" + max + " =", monitor.brightness); } } } else { // Internal backlight - parse the response which includes device path - var lines = dataText.split("\n") + var lines = dataText.split("\n"); if (lines.length >= 3) { - monitor.backlightDevice = lines[0] - monitor.brightnessPath = monitor.backlightDevice + "/brightness" - monitor.maxBrightnessPath = monitor.backlightDevice + "/max_brightness" + monitor.backlightDevice = lines[0]; + monitor.brightnessPath = monitor.backlightDevice + "/brightness"; + monitor.maxBrightnessPath = monitor.backlightDevice + "/max_brightness"; - var current = parseInt(lines[1]) - var max = parseInt(lines[2]) + var current = parseInt(lines[1]); + var max = parseInt(lines[2]); if (!isNaN(current) && !isNaN(max) && max > 0) { - monitor.maxBrightness = max - monitor.brightness = current / max - Logger.d("Brightness", "Internal brightness:", current + "/" + max + " =", monitor.brightness) - Logger.d("Brightness", "Using backlight device:", monitor.backlightDevice) + monitor.maxBrightness = max; + monitor.brightness = current / max; + Logger.d("Brightness", "Internal brightness:", current + "/" + max + " =", monitor.brightness); + Logger.d("Brightness", "Using backlight device:", monitor.backlightDevice); } } } // Always update - monitor.brightnessUpdated(monitor.brightness) - root.monitorBrightnessChanged(monitor, monitor.brightness) + monitor.brightnessUpdated(monitor.brightness); + root.monitorBrightnessChanged(monitor, monitor.brightness); } } } @@ -270,74 +269,74 @@ Singleton { interval: 100 onTriggered: { if (!isNaN(monitor.queuedBrightness)) { - monitor.setBrightness(monitor.queuedBrightness) - monitor.queuedBrightness = NaN + monitor.setBrightness(monitor.queuedBrightness); + monitor.queuedBrightness = NaN; } } } function setBrightnessDebounced(value: real): void { - monitor.queuedBrightness = value - timer.start() + monitor.queuedBrightness = value; + timer.start(); } function increaseBrightness(): void { - const value = !isNaN(monitor.queuedBrightness) ? monitor.queuedBrightness : monitor.brightness + const value = !isNaN(monitor.queuedBrightness) ? monitor.queuedBrightness : monitor.brightness; // Enforce minimum brightness if enabled if (Settings.data.brightness.enforceMinimum && value <= minBrightnessValue) { - setBrightnessDebounced(Math.max(stepSize, minBrightnessValue)) + setBrightnessDebounced(Math.max(stepSize, minBrightnessValue)); } else { // Normal brightness increase - setBrightnessDebounced(value + stepSize) + setBrightnessDebounced(value + stepSize); } } function decreaseBrightness(): void { - const value = !isNaN(monitor.queuedBrightness) ? monitor.queuedBrightness : monitor.brightness - setBrightnessDebounced(value - stepSize) + const value = !isNaN(monitor.queuedBrightness) ? monitor.queuedBrightness : monitor.brightness; + setBrightnessDebounced(value - stepSize); } function setBrightness(value: real): void { - value = Math.max(minBrightnessValue, Math.min(1, value)) - var rounded = Math.round(value * 100) + value = Math.max(minBrightnessValue, Math.min(1, value)); + var rounded = Math.round(value * 100); if (timer.running) { - monitor.queuedBrightness = value - return + monitor.queuedBrightness = value; + return; } // Update internal value and trigger UI feedback - monitor.brightness = value - monitor.brightnessUpdated(value) - root.monitorBrightnessChanged(monitor, monitor.brightness) + monitor.brightness = value; + monitor.brightnessUpdated(value); + root.monitorBrightnessChanged(monitor, monitor.brightness); if (isAppleDisplay) { - monitor.ignoreNextChange = true - Quickshell.execDetached(["asdbctl", "set", rounded]) + monitor.ignoreNextChange = true; + Quickshell.execDetached(["asdbctl", "set", rounded]); } else if (isDdc) { - monitor.ignoreNextChange = true - Quickshell.execDetached(["ddcutil", "-b", busNum, "setvcp", "10", rounded]) + monitor.ignoreNextChange = true; + Quickshell.execDetached(["ddcutil", "-b", busNum, "setvcp", "10", rounded]); } else { - monitor.ignoreNextChange = true - Quickshell.execDetached(["brightnessctl", "s", rounded + "%"]) + monitor.ignoreNextChange = true; + Quickshell.execDetached(["brightnessctl", "s", rounded + "%"]); } if (isDdc) { - timer.restart() + timer.restart(); } } function initBrightness(): void { if (isAppleDisplay) { - initProc.command = ["asdbctl", "get"] + initProc.command = ["asdbctl", "get"]; } else if (isDdc) { - initProc.command = ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] + initProc.command = ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"]; } else { // Internal backlight - find the first available backlight device and get its info // This now returns: device_path, current_brightness, max_brightness (on separate lines) - initProc.command = ["sh", "-c", "for dev in /sys/class/backlight/*; do " + " if [ -f \"$dev/brightness\" ] && [ -f \"$dev/max_brightness\" ]; then " + " echo \"$dev\"; " + " cat \"$dev/brightness\"; " + " cat \"$dev/max_brightness\"; " + " break; " + " fi; " + "done"] + initProc.command = ["sh", "-c", "for dev in /sys/class/backlight/*; do " + " if [ -f \"$dev/brightness\" ] && [ -f \"$dev/max_brightness\" ]; then " + " echo \"$dev\"; " + " cat \"$dev/brightness\"; " + " cat \"$dev/max_brightness\"; " + " break; " + " fi; " + "done"]; } - initProc.running = true + initProc.running = true; } onBusNumChanged: initBrightness() diff --git a/Services/Keyboard/ClipboardService.qml b/Services/Keyboard/ClipboardService.qml index bb224a28..b54fb260 100644 --- a/Services/Keyboard/ClipboardService.qml +++ b/Services/Keyboard/ClipboardService.qml @@ -42,16 +42,15 @@ Singleton { // Check if cliphist is available Component.onCompleted: { - checkCliphistAvailability() + checkCliphistAvailability(); } // Check dependency availability function checkCliphistAvailability() { if (dependencyChecked) - return - - dependencyCheckProcess.command = ["which", "cliphist"] - dependencyCheckProcess.running = true + return; + dependencyCheckProcess.command = ["which", "cliphist"]; + dependencyCheckProcess.running = true; } // Process to check if cliphist is available @@ -59,18 +58,18 @@ Singleton { id: dependencyCheckProcess stdout: StdioCollector {} onExited: (exitCode, exitStatus) => { - root.dependencyChecked = true + root.dependencyChecked = true; if (exitCode === 0) { - root.cliphistAvailable = true + root.cliphistAvailable = true; // Start watchers if feature is enabled if (root.active) { - startWatchers() + startWatchers(); } } else { - root.cliphistAvailable = false + root.cliphistAvailable = false; // Show toast notification if feature is enabled but cliphist is missing if (Settings.data.appLauncher.enableClipboardHistory) { - ToastService.showWarning(I18n.tr("toast.clipboard.unavailable"), I18n.tr("toast.clipboard.unavailable-desc"), 6000) + ToastService.showWarning(I18n.tr("toast.clipboard.unavailable"), I18n.tr("toast.clipboard.unavailable-desc"), 6000); } } } @@ -79,12 +78,12 @@ Singleton { // Start/stop watchers when enabled changes onActiveChanged: { if (root.active) { - startWatchers() + startWatchers(); } else { - stopWatchers() - loading = false + stopWatchers(); + loading = false; // Optional: clear items to avoid stale UI - items = [] + items = []; } } @@ -101,53 +100,53 @@ Singleton { id: listProc stdout: StdioCollector {} onExited: (exitCode, exitStatus) => { - const out = String(stdout.text) - const lines = out.split('\n').filter(l => l.length > 0) + const out = String(stdout.text); + const lines = out.split('\n').filter(l => l.length > 0); // cliphist list default format: " " or "\t" const parsed = lines.map(l => { - let id = "" - let preview = "" - const m = l.match(/^(\d+)\s+(.+)$/) + let id = ""; + let preview = ""; + const m = l.match(/^(\d+)\s+(.+)$/); if (m) { - id = m[1] - preview = m[2] + id = m[1]; + preview = m[2]; } else { - const tab = l.indexOf('\t') - id = tab > -1 ? l.slice(0, tab) : l - preview = tab > -1 ? l.slice(tab + 1) : "" + const tab = l.indexOf('\t'); + id = tab > -1 ? l.slice(0, tab) : l; + preview = tab > -1 ? l.slice(tab + 1) : ""; } - const lower = preview.toLowerCase() - const isImage = lower.startsWith("[image]") || lower.includes(" binary data ") + const lower = preview.toLowerCase(); + const isImage = lower.startsWith("[image]") || lower.includes(" binary data "); // Best-effort mime guess from preview - var mime = "text/plain" + var mime = "text/plain"; if (isImage) { if (lower.includes(" png")) - mime = "image/png" + mime = "image/png"; else if (lower.includes(" jpg") || lower.includes(" jpeg")) - mime = "image/jpeg" + mime = "image/jpeg"; else if (lower.includes(" webp")) - mime = "image/webp" + mime = "image/webp"; else if (lower.includes(" gif")) - mime = "image/gif" + mime = "image/gif"; else - mime = "image/*" + mime = "image/*"; } // Record first seen time for new ids (approximate copy time) if (!root.firstSeenById[id]) { - root.firstSeenById[id] = Time.timestamp + root.firstSeenById[id] = Time.timestamp; } return { "id": id, "preview": preview, "isImage": isImage, "mime": mime - } - }) - items = parsed - loading = false + }; + }); + items = parsed; + loading = false; // Emit the signal for subscribers - root.listCompleted() + root.listCompleted(); } } @@ -155,12 +154,12 @@ Singleton { id: decodeProc stdout: StdioCollector {} onExited: (exitCode, exitStatus) => { - const out = String(stdout.text) + const out = String(stdout.text); if (root._decodeCallback) { try { - root._decodeCallback(out) + root._decodeCallback(out); } finally { - root._decodeCallback = null + root._decodeCallback = null; } } } @@ -176,23 +175,21 @@ Singleton { id: decodeB64Proc stdout: StdioCollector {} onExited: (exitCode, exitStatus) => { - const b64 = String(stdout.text).trim() + const b64 = String(stdout.text).trim(); if (root._b64CurrentCb) { - const url = `data:${root._b64CurrentMime};base64,${b64}` + const url = `data:${root._b64CurrentMime};base64,${b64}`; try { - root._b64CurrentCb(url) - } catch (e) { - - } + root._b64CurrentCb(url); + } catch (e) {} } if (root._b64CurrentId !== "") { - root.imageDataById[root._b64CurrentId] = `data:${root._b64CurrentMime};base64,${b64}` - root.revision += 1 + root.imageDataById[root._b64CurrentId] = `data:${root._b64CurrentMime};base64,${b64}`; + root.revision += 1; } - root._b64CurrentCb = null - root._b64CurrentMime = "" - root._b64CurrentId = "" - Qt.callLater(root._startNextB64) + root._b64CurrentCb = null; + root._b64CurrentMime = ""; + root._b64CurrentId = ""; + Qt.callLater(root._startNextB64); } } @@ -204,8 +201,8 @@ Singleton { // Auto-restart if watcher dies if (root.autoWatch) Qt.callLater(() => { - running = true - }) + running = true; + }); } } Process { @@ -214,120 +211,120 @@ Singleton { onExited: (exitCode, exitStatus) => { if (root.autoWatch) Qt.callLater(() => { - running = true - }) + running = true; + }); } } function startWatchers() { if (!root.active || !autoWatch || watchersStarted || !root.cliphistAvailable) - return - watchersStarted = true + return; + watchersStarted = true; // Start text watcher - watchText.command = ["wl-paste", "--type", "text", "--watch", "cliphist", "store"] - watchText.running = true + watchText.command = ["wl-paste", "--type", "text", "--watch", "cliphist", "store"]; + watchText.running = true; // Start image watcher - watchImage.command = ["wl-paste", "--type", "image", "--watch", "cliphist", "store"] - watchImage.running = true + watchImage.command = ["wl-paste", "--type", "image", "--watch", "cliphist", "store"]; + watchImage.running = true; } function stopWatchers() { if (!watchersStarted) - return - watchText.running = false - watchImage.running = false - watchersStarted = false + return; + watchText.running = false; + watchImage.running = false; + watchersStarted = false; } function list(maxPreviewWidth) { if (!root.active || !root.cliphistAvailable) { - return + return; } if (listProc.running) - return - loading = true - const width = maxPreviewWidth || 100 - listProc.command = ["cliphist", "list", "-preview-width", String(width)] - listProc.running = true + return; + loading = true; + const width = maxPreviewWidth || 100; + listProc.command = ["cliphist", "list", "-preview-width", String(width)]; + listProc.running = true; } function decode(id, cb) { if (!root.cliphistAvailable) { if (cb) - cb("") - return + cb(""); + return; } - root._decodeCallback = cb - decodeProc.command = ["cliphist", "decode", id] - decodeProc.running = true + root._decodeCallback = cb; + decodeProc.command = ["cliphist", "decode", id]; + decodeProc.running = true; } function decodeToDataUrl(id, mime, cb) { if (!root.cliphistAvailable) { if (cb) - cb("") - return + cb(""); + return; } // If cached, return immediately if (root.imageDataById[id]) { if (cb) - cb(root.imageDataById[id]) - return + cb(root.imageDataById[id]); + return; } // Queue request; ensures single process handles sequentially root._b64Queue.push({ "id": id, "mime": mime || "image/*", "cb": cb - }) + }); if (!decodeB64Proc.running && root._b64CurrentCb === null) { - _startNextB64() + _startNextB64(); } } function getImageData(id) { if (id === undefined) { - return null + return null; } - return root.imageDataById[id] + return root.imageDataById[id]; } function _startNextB64() { if (root._b64Queue.length === 0 || !root.cliphistAvailable) - return - const job = root._b64Queue.shift() - root._b64CurrentCb = job.cb - root._b64CurrentMime = job.mime - root._b64CurrentId = job.id - decodeB64Proc.command = ["sh", "-lc", `cliphist decode ${job.id} | base64 -w 0`] - decodeB64Proc.running = true + return; + const job = root._b64Queue.shift(); + root._b64CurrentCb = job.cb; + root._b64CurrentMime = job.mime; + root._b64CurrentId = job.id; + decodeB64Proc.command = ["sh", "-lc", `cliphist decode ${job.id} | base64 -w 0`]; + decodeB64Proc.running = true; } function copyToClipboard(id) { if (!root.cliphistAvailable) { - return + return; } // decode and pipe to wl-copy; implement via shell to preserve binary - copyProc.command = ["sh", "-lc", `cliphist decode ${id} | wl-copy`] - copyProc.running = true + copyProc.command = ["sh", "-lc", `cliphist decode ${id} | wl-copy`]; + copyProc.running = true; } function deleteById(id) { if (!root.cliphistAvailable) { - return + return; } - Quickshell.execDetached(["cliphist", "delete", id]) - revision++ - Qt.callLater(() => list()) + Quickshell.execDetached(["cliphist", "delete", id]); + revision++; + Qt.callLater(() => list()); } function wipeAll() { if (!root.cliphistAvailable) { - return + return; } - Quickshell.execDetached(["cliphist", "wipe"]) - revision++ - Qt.callLater(() => list()) + Quickshell.execDetached(["cliphist", "wipe"]); + revision++; + Qt.callLater(() => list()); } } diff --git a/Services/Keyboard/KeyboardLayoutService.qml b/Services/Keyboard/KeyboardLayoutService.qml index d9043c8b..9672c584 100644 --- a/Services/Keyboard/KeyboardLayoutService.qml +++ b/Services/Keyboard/KeyboardLayoutService.qml @@ -15,76 +15,76 @@ Singleton { // Updates current layout from various format strings. Called by compositors function setCurrentLayout(layoutString) { - root.currentLayout = extractLayoutCode(layoutString) + root.currentLayout = extractLayoutCode(layoutString); } // Extract layout code from various format strings using Commons data function extractLayoutCode(layoutString) { if (!layoutString) - return I18n.tr("system.unknown-layout") + return I18n.tr("system.unknown-layout"); - const str = layoutString.toLowerCase() + const str = layoutString.toLowerCase(); // If it's already a short code (2-3 chars), return as-is if (/^[a-z]{2,3}(\+.*)?$/.test(str)) { - return str.split('+')[0] + return str.split('+')[0]; } // Extract from parentheses like "English (US)" - const parenMatch = str.match(/\(([a-z]{2,3})\)/) + const parenMatch = str.match(/\(([a-z]{2,3})\)/); if (parenMatch) { - return parenMatch[1] + return parenMatch[1]; } // Check for exact matches or partial matches in language map from Commons - const entries = Object.entries(languageMap) + const entries = Object.entries(languageMap); for (var i = 0; i < entries.length; i++) { - const lang = entries[i][0] - const code = entries[i][1] + const lang = entries[i][0]; + const code = entries[i][1]; if (str.includes(lang)) { - return code + return code; } } // If nothing matches, try first 2-3 characters if they look like a code - const codeMatch = str.match(/^([a-z]{2,3})/) - return codeMatch ? codeMatch[1] : I18n.tr("system.unknown-layout") + const codeMatch = str.match(/^([a-z]{2,3})/); + return codeMatch ? codeMatch[1] : I18n.tr("system.unknown-layout"); } // Watch for layout changes and show toast onCurrentLayoutChanged: { // Update previousLayout after checking for changes - const layoutChanged = isInitialized && currentLayout !== previousLayout && currentLayout !== I18n.tr("system.unknown-layout") && previousLayout !== "" && previousLayout !== I18n.tr("system.unknown-layout") + const layoutChanged = isInitialized && currentLayout !== previousLayout && currentLayout !== I18n.tr("system.unknown-layout") && previousLayout !== "" && previousLayout !== I18n.tr("system.unknown-layout"); if (layoutChanged) { if (Settings.data.notifications.enableKeyboardLayoutToast) { const message = I18n.tr("toast.keyboard-layout.changed", { "layout": currentLayout.toUpperCase() - }) - ToastService.showNotice(message, "", "", 2000) + }); + ToastService.showNotice(message, "", "", 2000); } - Logger.d("KeyboardLayout", "Layout changed from", previousLayout, "to", currentLayout) + Logger.d("KeyboardLayout", "Layout changed from", previousLayout, "to", currentLayout); } // Update previousLayout for next comparison - previousLayout = currentLayout + previousLayout = currentLayout; } Component.onCompleted: { - Logger.i("KeyboardLayout", "Service started") + Logger.i("KeyboardLayout", "Service started"); // Mark as initialized after a delay to allow first layout update to complete // This prevents showing a toast on the initial load - initializationTimer.start() + initializationTimer.start(); } Timer { id: initializationTimer interval: 2000 // Wait 2 seconds for first layout update to complete onTriggered: { - isInitialized = true + isInitialized = true; // Set previousLayout to current value after initialization - previousLayout = currentLayout - Logger.d("KeyboardLayout", "Service initialized, current layout:", currentLayout) + previousLayout = currentLayout; + Logger.d("KeyboardLayout", "Service initialized, current layout:", currentLayout); } } diff --git a/Services/Keyboard/LockKeysService.qml b/Services/Keyboard/LockKeysService.qml index 2a7a274d..e7dafd1b 100644 --- a/Services/Keyboard/LockKeysService.qml +++ b/Services/Keyboard/LockKeysService.qml @@ -28,30 +28,30 @@ scroll=0; cat /sys/class/leds/input*::scrolllock/brightness 2>/dev/null | grep - stdout: StdioCollector { onStreamFinished: { - var lines = this.text.trim().split('\n') + var lines = this.text.trim().split('\n'); for (var i = 0; i < lines.length; i++) { - var parts = lines[i].split(':') + var parts = lines[i].split(':'); if (parts.length === 2) { - var key = parts[0] - var newState = (parts[1] === '1') + var key = parts[0]; + var newState = (parts[1] === '1'); if (key === "caps") { if (root.capsLockOn !== newState) { - root.capsLockOn = newState - root.capsLockChanged(newState) - Logger.i("LockKeysService", "Caps Lock:", capsLockOn) + root.capsLockOn = newState; + root.capsLockChanged(newState); + Logger.i("LockKeysService", "Caps Lock:", capsLockOn); } } else if (key === "num") { if (root.numLockOn !== newState) { - root.numLockOn = newState - root.numLockChanged(newState) - Logger.i("LockKeysService", "Num Lock:", numLockOn) + root.numLockOn = newState; + root.numLockChanged(newState); + Logger.i("LockKeysService", "Num Lock:", numLockOn); } } else if (key === "scroll") { if (root.scrollLockOn !== newState) { - root.scrollLockOn = newState - root.scrollLockChanged(newState) - Logger.i("LockKeysService", "Scroll Lock:", scrollLockOn) + root.scrollLockOn = newState; + root.scrollLockChanged(newState); + Logger.i("LockKeysService", "Scroll Lock:", scrollLockOn); } } } @@ -61,7 +61,7 @@ scroll=0; cat /sys/class/leds/input*::scrolllock/brightness 2>/dev/null | grep - stderr: StdioCollector { onStreamFinished: { if (this.text.trim().length > 0) - Logger.i("LockKeysService", "Error running state check:", this.text.trim()) + Logger.i("LockKeysService", "Error running state check:", this.text.trim()); } } } @@ -73,13 +73,13 @@ scroll=0; cat /sys/class/leds/input*::scrolllock/brightness 2>/dev/null | grep - repeat: true onTriggered: { if (!stateCheckProcess.running) { - stateCheckProcess.running = true + stateCheckProcess.running = true; } } } Component.onCompleted: { - Logger.i("LockKeysService", "Service started, performing initial state check.") - stateCheckProcess.running = true + Logger.i("LockKeysService", "Service started, performing initial state check."); + stateCheckProcess.running = true; } } diff --git a/Services/Location/CalendarService.qml b/Services/Location/CalendarService.qml index 75a9a273..c0626f49 100644 --- a/Services/Location/CalendarService.qml +++ b/Services/Location/CalendarService.qml @@ -37,20 +37,20 @@ Singleton { } onLoadFailed: { - cacheAdapter.cachedEvents = ([]) - cacheAdapter.cachedCalendars = ([]) - cacheAdapter.lastUpdate = "" + cacheAdapter.cachedEvents = ([]); + cacheAdapter.cachedCalendars = ([]); + cacheAdapter.lastUpdate = ""; } onLoaded: { - loadFromCache() + loadFromCache(); } } Component.onCompleted: { - Logger.i("Calendar", "Service started") - loadFromCache() - checkAvailability() + Logger.i("Calendar", "Service started"); + loadFromCache(); + checkAvailability(); } // Save cache with debounce @@ -61,23 +61,23 @@ Singleton { } function saveCache() { - saveDebounce.restart() + saveDebounce.restart(); } // Load events and calendars from cache function loadFromCache() { if (cacheAdapter.cachedEvents && cacheAdapter.cachedEvents.length > 0) { - root.events = cacheAdapter.cachedEvents - Logger.d("Calendar", `Loaded ${cacheAdapter.cachedEvents.length} cached event(s)`) + root.events = cacheAdapter.cachedEvents; + Logger.d("Calendar", `Loaded ${cacheAdapter.cachedEvents.length} cached event(s)`); } if (cacheAdapter.cachedCalendars && cacheAdapter.cachedCalendars.length > 0) { - root.calendars = cacheAdapter.cachedCalendars - Logger.d("Calendar", `Loaded ${cacheAdapter.cachedCalendars.length} cached calendar(s)`) + root.calendars = cacheAdapter.cachedCalendars; + Logger.d("Calendar", `Loaded ${cacheAdapter.cachedCalendars.length} cached calendar(s)`); } if (cacheAdapter.lastUpdate) { - Logger.d("Calendar", `Cache last updated: ${cacheAdapter.lastUpdate}`) + Logger.d("Calendar", `Cache last updated: ${cacheAdapter.lastUpdate}`); } } @@ -93,43 +93,42 @@ Singleton { // Core functions function checkAvailability() { if (Settings.data.location.showCalendarEvents) { - availabilityCheckProcess.running = true + availabilityCheckProcess.running = true; } else { - root.available = false + root.available = false; } } function loadCalendars() { - listCalendarsProcess.running = true + listCalendarsProcess.running = true; } function loadEvents(daysAhead = 31, daysBehind = 14) { if (!Settings.data.location.showCalendarEvents) { - root.loading = false - root.events = [] - return + root.loading = false; + root.events = []; + return; } if (loading) - return + return; + loading = true; + lastError = ""; - loading = true - lastError = "" + const now = new Date(); + const startDate = new Date(now.getTime() - (daysBehind * 24 * 60 * 60 * 1000)); + const endDate = new Date(now.getTime() + (daysAhead * 24 * 60 * 60 * 1000)); - const now = new Date() - const startDate = new Date(now.getTime() - (daysBehind * 24 * 60 * 60 * 1000)) - const endDate = new Date(now.getTime() + (daysAhead * 24 * 60 * 60 * 1000)) + loadEventsProcess.startTime = Math.floor(startDate.getTime() / 1000); + loadEventsProcess.endTime = Math.floor(endDate.getTime() / 1000); + loadEventsProcess.running = true; - loadEventsProcess.startTime = Math.floor(startDate.getTime() / 1000) - loadEventsProcess.endTime = Math.floor(endDate.getTime() / 1000) - loadEventsProcess.running = true - - Logger.d("Calendar", `Loading events (${daysBehind} days behind, ${daysAhead} days ahead): ${startDate.toLocaleDateString()} to ${endDate.toLocaleDateString()}`) + Logger.d("Calendar", `Loading events (${daysBehind} days behind, ${daysAhead} days ahead): ${startDate.toLocaleDateString()} to ${endDate.toLocaleDateString()}`); } // Helper to format date/time function formatDateTime(timestamp) { - const date = new Date(timestamp * 1000) - return Qt.formatDateTime(date, "yyyy-MM-dd hh:mm") + const date = new Date(timestamp * 1000); + return Qt.formatDateTime(date, "yyyy-MM-dd hh:mm"); } // Process to check for evolution-data-server libraries @@ -140,15 +139,15 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const result = text.trim() - root.available = result === "available" + const result = text.trim(); + root.available = result === "available"; if (root.available) { - Logger.i("Calendar", "EDS libraries available") - loadCalendars() + Logger.i("Calendar", "EDS libraries available"); + loadCalendars(); } else { - Logger.w("Calendar", "EDS libraries not available: " + result) - root.lastError = "Evolution Data Server libraries not installed" + Logger.w("Calendar", "EDS libraries not available: " + result); + root.lastError = "Evolution Data Server libraries not installed"; } } } @@ -156,9 +155,9 @@ Singleton { stderr: StdioCollector { onStreamFinished: { if (text.trim()) { - Logger.d("Calendar", "Availability check error: " + text) - root.available = false - root.lastError = "Failed to check library availability" + Logger.d("Calendar", "Availability check error: " + text); + root.available = false; + root.lastError = "Failed to check library availability"; } } } @@ -173,24 +172,24 @@ Singleton { stdout: StdioCollector { onStreamFinished: { try { - const result = JSON.parse(text.trim()) - root.calendars = result - cacheAdapter.cachedCalendars = result - saveCache() + const result = JSON.parse(text.trim()); + root.calendars = result; + cacheAdapter.cachedCalendars = result; + saveCache(); - Logger.d("Calendar", `Found ${result.length} calendar(s)`) + Logger.d("Calendar", `Found ${result.length} calendar(s)`); // Auto-load events after discovering calendars // Only load if we have calendars and no cached events if (result.length > 0 && root.events.length === 0) { - loadEvents() + loadEvents(); } else if (result.length > 0) { // If we already have cached events, load in background - loadEvents() + loadEvents(); } } catch (e) { - Logger.d("Calendar", "Failed to parse calendars: " + e) - root.lastError = "Failed to parse calendar list" + Logger.d("Calendar", "Failed to parse calendars: " + e); + root.lastError = "Failed to parse calendar list"; } } } @@ -198,8 +197,8 @@ Singleton { stderr: StdioCollector { onStreamFinished: { if (text.trim()) { - Logger.d("Calendar", "List calendars error: " + text) - root.lastError = text.trim() + Logger.d("Calendar", "List calendars error: " + text); + root.lastError = text.trim(); } } } @@ -216,24 +215,24 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - root.loading = false + root.loading = false; try { - const result = JSON.parse(text.trim()) - root.events = result - cacheAdapter.cachedEvents = result - cacheAdapter.lastUpdate = new Date().toISOString() - saveCache() + const result = JSON.parse(text.trim()); + root.events = result; + cacheAdapter.cachedEvents = result; + cacheAdapter.lastUpdate = new Date().toISOString(); + saveCache(); - Logger.d("Calendar", `Loaded ${result.length} event(s)`) + Logger.d("Calendar", `Loaded ${result.length} event(s)`); } catch (e) { - Logger.d("Calendar", "Failed to parse events: " + e) - root.lastError = "Failed to parse events" + Logger.d("Calendar", "Failed to parse events: " + e); + root.lastError = "Failed to parse events"; // Fall back to cached events if available if (cacheAdapter.cachedEvents.length > 0) { - root.events = cacheAdapter.cachedEvents - Logger.d("Calendar", "Using cached events") + root.events = cacheAdapter.cachedEvents; + Logger.d("Calendar", "Using cached events"); } } } @@ -241,16 +240,16 @@ Singleton { stderr: StdioCollector { onStreamFinished: { - root.loading = false + root.loading = false; if (text.trim()) { - Logger.d("Calendar", "Load events error: " + text) - root.lastError = text.trim() + Logger.d("Calendar", "Load events error: " + text); + root.lastError = text.trim(); // Fall back to cached events if available if (cacheAdapter.cachedEvents.length > 0) { - root.events = cacheAdapter.cachedEvents - Logger.d("Calendar", "Using cached events due to error") + root.events = cacheAdapter.cachedEvents; + Logger.d("Calendar", "Using cached events due to error"); } } } diff --git a/Services/Location/DarkModeService.qml b/Services/Location/DarkModeService.qml index e7c3315c..3e465fa9 100644 --- a/Services/Location/DarkModeService.qml +++ b/Services/Location/DarkModeService.qml @@ -15,12 +15,12 @@ Singleton { enabled: Settings.data.colorSchemes.schedulingMode == "location" function onWeatherChanged() { if (LocationService.data.weather !== null) { - const changes = root.collectWeatherChanges(LocationService.data.weather) + const changes = root.collectWeatherChanges(LocationService.data.weather); if (!root.initComplete) { - root.initComplete = true - root.applyCurrentMode(changes) + root.initComplete = true; + root.applyCurrentMode(changes); } - root.scheduleNextMode(changes) + root.scheduleNextMode(changes); } } } @@ -29,140 +29,145 @@ Singleton { target: Settings.data.colorSchemes enabled: Settings.data.colorSchemes.schedulingMode == "manual" function onManualSunriseChanged() { - const changes = root.collectManualChanges() - root.applyCurrentMode(changes) - root.scheduleNextMode(changes) + const changes = root.collectManualChanges(); + root.applyCurrentMode(changes); + root.scheduleNextMode(changes); } function onManualSunsetChanged() { - const changes = root.collectManualChanges() - root.applyCurrentMode(changes) - root.scheduleNextMode(changes) + const changes = root.collectManualChanges(); + root.applyCurrentMode(changes); + root.scheduleNextMode(changes); } } Connections { target: Settings.data.colorSchemes function onSchedulingModeChanged() { - root.init() + root.init(); } } Timer { id: timer onTriggered: { - Settings.data.colorSchemes.darkMode = root.nextDarkModeState + Settings.data.colorSchemes.darkMode = root.nextDarkModeState; if (LocationService.data.weather !== null) { - const changes = root.collectWeatherChanges(LocationService.data.weather) - root.scheduleNextMode(changes) + const changes = root.collectWeatherChanges(LocationService.data.weather); + root.scheduleNextMode(changes); } } } function init() { - Logger.i("DarkModeService", "Service started") + Logger.i("DarkModeService", "Service started"); if (Settings.data.colorSchemes.schedulingMode == "manual") { - const changes = collectManualChanges() - initComplete = true - applyCurrentMode(changes) - scheduleNextMode(changes) + const changes = collectManualChanges(); + initComplete = true; + applyCurrentMode(changes); + scheduleNextMode(changes); } if (Settings.data.colorSchemes.schedulingMode == "location" && LocationService.data.weather) { - const changes = collectWeatherChanges(LocationService.data.weather) - initComplete = true - applyCurrentMode(changes) - scheduleNextMode(changes) + const changes = collectWeatherChanges(LocationService.data.weather); + initComplete = true; + applyCurrentMode(changes); + scheduleNextMode(changes); } } function parseTime(timeString) { - const parts = timeString.split(":").map(Number) + const parts = timeString.split(":").map(Number); return { "hour": parts[0], "minute": parts[1] - } + }; } function collectManualChanges() { - const sunriseTime = parseTime(Settings.data.colorSchemes.manualSunrise) - const sunsetTime = parseTime(Settings.data.colorSchemes.manualSunset) + const sunriseTime = parseTime(Settings.data.colorSchemes.manualSunrise); + const sunsetTime = parseTime(Settings.data.colorSchemes.manualSunset); - const now = new Date() - const year = now.getFullYear() - const month = now.getMonth() - const day = now.getDate() + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + const day = now.getDate(); - const yesterdaysSunset = new Date(year, month, day - 1, sunsetTime.hour, sunsetTime.minute) - const todaysSunrise = new Date(year, month, day, sunriseTime.hour, sunriseTime.minute) - const todaysSunset = new Date(year, month, day, sunsetTime.hour, sunsetTime.minute) - const tomorrowsSunrise = new Date(year, month, day + 1, sunriseTime.hour, sunriseTime.minute) + const yesterdaysSunset = new Date(year, month, day - 1, sunsetTime.hour, sunsetTime.minute); + const todaysSunrise = new Date(year, month, day, sunriseTime.hour, sunriseTime.minute); + const todaysSunset = new Date(year, month, day, sunsetTime.hour, sunsetTime.minute); + const tomorrowsSunrise = new Date(year, month, day + 1, sunriseTime.hour, sunriseTime.minute); - return [{ - "time": yesterdaysSunset.getTime(), - "darkMode": true - }, { - "time": todaysSunrise.getTime(), - "darkMode": false - }, { - "time": todaysSunset.getTime(), - "darkMode": true - }, { - "time": tomorrowsSunrise.getTime(), - "darkMode": false - }] + return [ + { + "time": yesterdaysSunset.getTime(), + "darkMode": true + }, + { + "time": todaysSunrise.getTime(), + "darkMode": false + }, + { + "time": todaysSunset.getTime(), + "darkMode": true + }, + { + "time": tomorrowsSunrise.getTime(), + "darkMode": false + } + ]; } function collectWeatherChanges(weather) { - const changes = [] + const changes = []; if (Date.now() < Date.parse(weather.daily.sunrise[0])) { // The sun has not risen yet changes.push({ "time": Date.now() - 1, "darkMode": true - }) + }); } for (var i = 0; i < weather.daily.sunrise.length; i++) { changes.push({ "time": Date.parse(weather.daily.sunrise[i]), "darkMode": false - }) + }); changes.push({ "time": Date.parse(weather.daily.sunset[i]), "darkMode": true - }) + }); } - return changes + return changes; } function applyCurrentMode(changes) { - const now = Date.now() + const now = Date.now(); // changes.findLast(change => change.time < now) // not available in QML... - let lastChange = null + let lastChange = null; for (var i = 0; i < changes.length; i++) { if (changes[i].time < now) { - lastChange = changes[i] + lastChange = changes[i]; } } if (lastChange) { - Settings.data.colorSchemes.darkMode = lastChange.darkMode - Logger.d("DarkModeService", `Reset: darkmode=${lastChange.darkMode}`) + Settings.data.colorSchemes.darkMode = lastChange.darkMode; + Logger.d("DarkModeService", `Reset: darkmode=${lastChange.darkMode}`); } } function scheduleNextMode(changes) { - const now = Date.now() - const nextChange = changes.find(change => change.time > now) + const now = Date.now(); + const nextChange = changes.find(change => change.time > now); if (nextChange) { - root.nextDarkModeState = nextChange.darkMode - timer.interval = nextChange.time - now - timer.restart() - Logger.d("DarkModeService", `Scheduled: darkmode=${nextChange.darkMode} in ${timer.interval} ms`) + root.nextDarkModeState = nextChange.darkMode; + timer.interval = nextChange.time - now; + timer.restart(); + Logger.d("DarkModeService", `Scheduled: darkmode=${nextChange.darkMode} in ${timer.interval} ms`); } } } diff --git a/Services/Location/LocationService.qml b/Services/Location/LocationService.qml index 775c9616..ac5e50fa 100644 --- a/Services/Location/LocationService.qml +++ b/Services/Location/LocationService.qml @@ -27,19 +27,19 @@ Singleton { printErrors: false onAdapterUpdated: saveTimer.start() onLoaded: { - Logger.d("Location", "Loaded cached data") + Logger.d("Location", "Loaded cached data"); // Initialize stable properties on load if (adapter.latitude !== "" && adapter.longitude !== "" && adapter.weatherLastFetch > 0) { - root.stableLatitude = adapter.latitude - root.stableLongitude = adapter.longitude - root.stableName = adapter.name - root.coordinatesReady = true - Logger.i("Location", "Coordinates ready") + root.stableLatitude = adapter.latitude; + root.stableLongitude = adapter.longitude; + root.stableName = adapter.name; + root.coordinatesReady = true; + Logger.i("Location", "Coordinates ready"); } - updateWeather() + updateWeather(); } onLoadFailed: function (error) { - updateWeather() + updateWeather(); } JsonAdapter { @@ -57,11 +57,11 @@ Singleton { // Helper property for UI components (outside JsonAdapter to avoid binding loops) readonly property string displayCoordinates: { if (!root.coordinatesReady || root.stableLatitude === "" || root.stableLongitude === "") { - return "" + return ""; } - const lat = parseFloat(root.stableLatitude).toFixed(4) - const lon = parseFloat(root.stableLongitude).toFixed(4) - return `${lat}, ${lon}` + const lat = parseFloat(root.stableLatitude).toFixed(4); + const lon = parseFloat(root.stableLongitude).toFixed(4); + return `${lat}, ${lon}`; } // Every 20s check if we need to fetch new weather @@ -71,7 +71,7 @@ Singleton { running: Settings.data.location.weatherEnabled || Settings.data.colorSchemes.schedulingMode == "location" repeat: true onTriggered: { - updateWeather() + updateWeather(); } } @@ -86,195 +86,194 @@ Singleton { function init() { // does nothing but ensure the singleton is created // do not remove - Logger.i("Location", "Service started") + Logger.i("Location", "Service started"); } // -------------------------------- function resetWeather() { - Logger.i("Location", "Resetting weather data") + Logger.i("Location", "Resetting weather data"); // Mark as changing to prevent UI updates - root.coordinatesReady = false + root.coordinatesReady = false; // Reset stable properties - root.stableLatitude = "" - root.stableLongitude = "" - root.stableName = "" + root.stableLatitude = ""; + root.stableLongitude = ""; + root.stableName = ""; // Reset core data - adapter.latitude = "" - adapter.longitude = "" - adapter.name = "" - adapter.weatherLastFetch = 0 - adapter.weather = null + adapter.latitude = ""; + adapter.longitude = ""; + adapter.name = ""; + adapter.weatherLastFetch = 0; + adapter.weather = null; // Try to fetch immediately - updateWeather() + updateWeather(); } // -------------------------------- function updateWeather() { if (!Settings.data.location.weatherEnabled) { - return + return; } if (isFetchingWeather) { - Logger.w("Location", "Weather is still fetching") - return + Logger.w("Location", "Weather is still fetching"); + return; } if ((adapter.weatherLastFetch === "") || (adapter.weather === null) || (adapter.latitude === "") || (adapter.longitude === "") || (adapter.name !== Settings.data.location.name) || (Time.timestamp >= adapter.weatherLastFetch + weatherUpdateFrequency)) { - getFreshWeather() + getFreshWeather(); } } // -------------------------------- function getFreshWeather() { - isFetchingWeather = true + isFetchingWeather = true; // Check if location name has changed - const locationChanged = data.name !== Settings.data.location.name + const locationChanged = data.name !== Settings.data.location.name; if (locationChanged) { - root.coordinatesReady = false - Logger.d("Location", "Location changed from", adapter.name, "to", Settings.data.location.name) + root.coordinatesReady = false; + Logger.d("Location", "Location changed from", adapter.name, "to", Settings.data.location.name); } if ((adapter.latitude === "") || (adapter.longitude === "") || locationChanged) { - _geocodeLocation(Settings.data.location.name, function (latitude, longitude, name, country) { - Logger.d("Location", "Geocoded", Settings.data.location.name, "to:", latitude, "/", longitude) + Logger.d("Location", "Geocoded", Settings.data.location.name, "to:", latitude, "/", longitude); // Save location name - adapter.name = Settings.data.location.name + adapter.name = Settings.data.location.name; // Save GPS coordinates - adapter.latitude = latitude.toString() - adapter.longitude = longitude.toString() + adapter.latitude = latitude.toString(); + adapter.longitude = longitude.toString(); - root.stableName = `${name}, ${country}` + root.stableName = `${name}, ${country}`; - _fetchWeather(latitude, longitude, errorCallback) - }, errorCallback) + _fetchWeather(latitude, longitude, errorCallback); + }, errorCallback); } else { - _fetchWeather(adapter.latitude, adapter.longitude, errorCallback) + _fetchWeather(adapter.latitude, adapter.longitude, errorCallback); } } // -------------------------------- function _geocodeLocation(locationName, callback, errorCallback) { - Logger.d("Location", "Geocoding location name") - var geoUrl = "https://assets.noctalia.dev/geocode.php?city=" + encodeURIComponent(locationName) + "&language=en&format=json" - var xhr = new XMLHttpRequest() + Logger.d("Location", "Geocoding location name"); + var geoUrl = "https://assets.noctalia.dev/geocode.php?city=" + encodeURIComponent(locationName) + "&language=en&format=json"; + var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { try { - var geoData = JSON.parse(xhr.responseText) + var geoData = JSON.parse(xhr.responseText); if (geoData.lat != null) { - callback(geoData.lat, geoData.lng, geoData.name, geoData.country) + callback(geoData.lat, geoData.lng, geoData.name, geoData.country); } else { - errorCallback("Location", "could not resolve location name") + errorCallback("Location", "could not resolve location name"); } } catch (e) { - errorCallback("Location", "Failed to parse geocoding data: " + e) + errorCallback("Location", "Failed to parse geocoding data: " + e); } } else { - errorCallback("Location", "Geocoding error: " + xhr.status) + errorCallback("Location", "Geocoding error: " + xhr.status); } } - } - xhr.open("GET", geoUrl) - xhr.send() + }; + xhr.open("GET", geoUrl); + xhr.send(); } // -------------------------------- function _fetchWeather(latitude, longitude, errorCallback) { - Logger.d("Location", "Fetching weather from api.open-meteo.com") - var url = "https://api.open-meteo.com/v1/forecast?latitude=" + latitude + "&longitude=" + longitude + "¤t_weather=true¤t=relativehumidity_2m,surface_pressure&daily=temperature_2m_max,temperature_2m_min,weathercode,sunset,sunrise&timezone=auto" - var xhr = new XMLHttpRequest() + Logger.d("Location", "Fetching weather from api.open-meteo.com"); + var url = "https://api.open-meteo.com/v1/forecast?latitude=" + latitude + "&longitude=" + longitude + "¤t_weather=true¤t=relativehumidity_2m,surface_pressure&daily=temperature_2m_max,temperature_2m_min,weathercode,sunset,sunrise&timezone=auto"; + var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { try { - var weatherData = JSON.parse(xhr.responseText) + var weatherData = JSON.parse(xhr.responseText); //console.log(JSON.stringify(weatherData)) // Save core data - data.weather = weatherData - data.weatherLastFetch = Time.timestamp + data.weather = weatherData; + data.weatherLastFetch = Time.timestamp; // Update stable display values only when complete and successful - root.stableLatitude = data.latitude = weatherData.latitude.toString() - root.stableLongitude = data.longitude = weatherData.longitude.toString() - root.coordinatesReady = true + root.stableLatitude = data.latitude = weatherData.latitude.toString(); + root.stableLongitude = data.longitude = weatherData.longitude.toString(); + root.coordinatesReady = true; - isFetchingWeather = false - Logger.i("Location", "Cached weather to disk - stable coordinates updated") + isFetchingWeather = false; + Logger.i("Location", "Cached weather to disk - stable coordinates updated"); } catch (e) { - errorCallback("Location", "Failed to parse weather data") + errorCallback("Location", "Failed to parse weather data"); } } else { - errorCallback("Location", "Weather fetch error: " + xhr.status) + errorCallback("Location", "Weather fetch error: " + xhr.status); } } - } - xhr.open("GET", url) - xhr.send() + }; + xhr.open("GET", url); + xhr.send(); } // -------------------------------- function errorCallback(module, message) { - Logger.e(module, message) - isFetchingWeather = false + Logger.e(module, message); + isFetchingWeather = false; } // -------------------------------- function weatherSymbolFromCode(code) { if (code === 0) - return "weather-sun" + return "weather-sun"; if (code === 1 || code === 2) - return "weather-cloud-sun" + return "weather-cloud-sun"; if (code === 3) - return "weather-cloud" + return "weather-cloud"; if (code >= 45 && code <= 48) - return "weather-cloud-haze" + return "weather-cloud-haze"; if (code >= 51 && code <= 67) - return "weather-cloud-rain" + return "weather-cloud-rain"; if (code >= 71 && code <= 77) - return "weather-cloud-snow" + return "weather-cloud-snow"; if (code >= 71 && code <= 77) - return "weather-cloud-snow" + return "weather-cloud-snow"; if (code >= 85 && code <= 86) - return "weather-cloud-snow" + return "weather-cloud-snow"; if (code >= 95 && code <= 99) - return "weather-cloud-lightning" - return "weather-cloud" + return "weather-cloud-lightning"; + return "weather-cloud"; } // -------------------------------- function weatherDescriptionFromCode(code) { if (code === 0) - return "Clear sky" + return "Clear sky"; if (code === 1) - return "Mainly clear" + return "Mainly clear"; if (code === 2) - return "Partly cloudy" + return "Partly cloudy"; if (code === 3) - return "Overcast" + return "Overcast"; if (code === 45 || code === 48) - return "Fog" + return "Fog"; if (code >= 51 && code <= 67) - return "Drizzle" + return "Drizzle"; if (code >= 71 && code <= 77) - return "Snow" + return "Snow"; if (code >= 80 && code <= 82) - return "Rain showers" + return "Rain showers"; if (code >= 95 && code <= 99) - return "Thunderstorm" - return "Unknown" + return "Thunderstorm"; + return "Unknown"; } // -------------------------------- function celsiusToFahrenheit(celsius) { - return 32 + celsius * 1.8 + return 32 + celsius * 1.8; } } diff --git a/Services/Location/NightLightService.qml b/Services/Location/NightLightService.qml index e25c828a..e418d4ad 100644 --- a/Services/Location/NightLightService.qml +++ b/Services/Location/NightLightService.qml @@ -16,66 +16,66 @@ Singleton { function apply() { // If using LocationService, wait for it to be ready if (!params.forced && params.autoSchedule && !LocationService.coordinatesReady) { - return + return; } - var command = buildCommand() + var command = buildCommand(); // Compare with previous command to avoid unecessary restart if (JSON.stringify(command) !== JSON.stringify(lastCommand)) { - lastCommand = command - runner.command = command + lastCommand = command; + runner.command = command; // Set running to false so it may restarts below if still enabled - runner.running = false + runner.running = false; } - runner.running = params.enabled + runner.running = params.enabled; } function buildCommand() { - var cmd = ["wlsunset"] + var cmd = ["wlsunset"]; if (params.forced) { // Force immediate full night temperature regardless of time // Keep distinct day/night temps but set times so we're effectively always in "night" - cmd.push("-t", `${params.nightTemp}`, "-T", `${params.dayTemp}`) + cmd.push("-t", `${params.nightTemp}`, "-T", `${params.dayTemp}`); // Night spans from sunset (00:00) to sunrise (23:59) covering almost the full day - cmd.push("-S", "23:59") // sunrise very late - cmd.push("-s", "00:00") // sunset at midnight + cmd.push("-S", "23:59"); // sunrise very late + cmd.push("-s", "00:00"); // sunset at midnight // Near-instant transition - cmd.push("-d", 1) + cmd.push("-d", 1); } else { - cmd.push("-t", `${params.nightTemp}`, "-T", `${params.dayTemp}`) + cmd.push("-t", `${params.nightTemp}`, "-T", `${params.dayTemp}`); if (params.autoSchedule) { - cmd.push("-l", `${LocationService.stableLatitude}`, "-L", `${LocationService.stableLongitude}`) + cmd.push("-l", `${LocationService.stableLatitude}`, "-L", `${LocationService.stableLongitude}`); } else { - cmd.push("-S", params.manualSunrise) - cmd.push("-s", params.manualSunset) + cmd.push("-S", params.manualSunrise); + cmd.push("-s", params.manualSunset); } - cmd.push("-d", 60 * 15) // 15min progressive fade at sunset/sunrise + cmd.push("-d", 60 * 15); // 15min progressive fade at sunset/sunrise } - return cmd + return cmd; } // Observe setting changes and location readiness Connections { target: Settings.data.nightLight function onEnabledChanged() { - apply() + apply(); // Toast: night light toggled - const enabled = !!Settings.data.nightLight.enabled - ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), enabled ? I18n.tr("toast.night-light.enabled") : I18n.tr("toast.night-light.disabled"), enabled ? "nightlight-on" : "nightlight-off") + const enabled = !!Settings.data.nightLight.enabled; + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), enabled ? I18n.tr("toast.night-light.enabled") : I18n.tr("toast.night-light.disabled"), enabled ? "nightlight-on" : "nightlight-off"); } function onForcedChanged() { - apply() + apply(); if (Settings.data.nightLight.enabled) { - ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), Settings.data.nightLight.forced ? I18n.tr("toast.night-light.forced") : I18n.tr("toast.night-light.normal"), Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), Settings.data.nightLight.forced ? I18n.tr("toast.night-light.forced") : I18n.tr("toast.night-light.normal"), Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on"); } } function onNightTempChanged() { - apply() + apply(); } function onDayTempChanged() { - apply() + apply(); } } @@ -83,7 +83,7 @@ Singleton { target: LocationService function onCoordinatesReadyChanged() { if (LocationService.coordinatesReady) { - apply() + apply(); } } } @@ -93,10 +93,10 @@ Singleton { id: runner running: false onStarted: { - Logger.i("NightLight", "Wlsunset started:", runner.command) + Logger.i("NightLight", "Wlsunset started:", runner.command); } onExited: function (code, status) { - Logger.i("NightLight", "Wlsunset exited:", code, status) + Logger.i("NightLight", "Wlsunset exited:", code, status); } } } diff --git a/Services/Media/AudioService.qml b/Services/Media/AudioService.qml index 49061371..cc269f18 100644 --- a/Services/Media/AudioService.qml +++ b/Services/Media/AudioService.qml @@ -12,12 +12,12 @@ Singleton { readonly property var nodes: Pipewire.nodes.values.reduce((acc, node) => { if (!node.isStream) { if (node.isSink) { - acc.sinks.push(node) + acc.sinks.push(node); } else if (node.audio) { - acc.sources.push(node) + acc.sources.push(node); } } - return acc + return acc; }, { "sources": [], "sinks": [] @@ -50,21 +50,21 @@ Singleton { function updateInputVolume() { if (source && source.audio) { - var vol = source.audio.volume + var vol = source.audio.volume; if (vol !== undefined && !isNaN(vol)) { - root._inputVolume = vol + root._inputVolume = vol; } // Don't reset to 0 if volume is undefined/NaN - preserve last known value - root._inputMuted = !!source.audio.muted + root._inputMuted = !!source.audio.muted; } else { // Only reset muted state - root._inputMuted = true + root._inputMuted = true; } } // Update input volume when source property changes onSourceChanged: { - updateInputVolume() + updateInputVolume(); } PwObjectTracker { @@ -75,22 +75,22 @@ Singleton { target: sink?.audio ? sink?.audio : null function onVolumeChanged() { - var vol = (sink?.audio.volume ?? 0) + var vol = (sink?.audio.volume ?? 0); if (isNaN(vol)) { - return + return; } // Only update if the value actually changed to prevent spurious signals if (Math.abs(root._volume - vol) > 0.001) { - root._volume = vol + root._volume = vol; } } function onMutedChanged() { - var newMuted = (sink?.audio.muted ?? true) + var newMuted = (sink?.audio.muted ?? true); // Only update if the value actually changed if (root._muted !== newMuted) { - root._muted = newMuted - Logger.i("AudioService", "OnMuteChanged:", root._muted) + root._muted = newMuted; + Logger.i("AudioService", "OnMuteChanged:", root._muted); } } } @@ -99,112 +99,113 @@ Singleton { target: source?.audio ? source?.audio : null function onVolumeChanged() { - var vol = source?.audio?.volume + var vol = source?.audio?.volume; if (vol === undefined || isNaN(vol)) { // Don't reset to 0 if volume is undefined/NaN - preserve last known value - return + return; } // Only update if the value actually changed to prevent spurious signals if (Math.abs(root._inputVolume - vol) > 0.001) { - root._inputVolume = vol + root._inputVolume = vol; } } function onMutedChanged() { - var newMuted = (source?.audio.muted ?? true) + var newMuted = (source?.audio.muted ?? true); // Only update if the value actually changed if (root._inputMuted !== newMuted) { - root._inputMuted = newMuted + root._inputMuted = newMuted; } } } Connections { target: Pipewire - function onDefaultAudioSinkChanged() {} + function onDefaultAudioSinkChanged() { + } function onDefaultAudioSourceChanged() { - updateInputVolume() + updateInputVolume(); } } function increaseVolume() { - setVolume(volume + stepVolume) + setVolume(volume + stepVolume); } function decreaseVolume() { - setVolume(volume - stepVolume) + setVolume(volume - stepVolume); } function setVolume(newVolume: real) { if (sink?.ready && sink?.audio) { // Clamp it accordingly - sink.audio.muted = false - sink.audio.volume = Math.max(0, Math.min(Settings.data.audio.volumeOverdrive ? 1.5 : 1.0, newVolume)) + sink.audio.muted = false; + sink.audio.volume = Math.max(0, Math.min(Settings.data.audio.volumeOverdrive ? 1.5 : 1.0, newVolume)); //Logger.i("AudioService", "SetVolume", sink.audio.volume); } else { - Logger.w("AudioService", "No sink available") + Logger.w("AudioService", "No sink available"); } } function setOutputMuted(muted: bool) { if (sink?.ready && sink?.audio) { - sink.audio.muted = muted + sink.audio.muted = muted; } else { - Logger.w("AudioService", "No sink available") + Logger.w("AudioService", "No sink available"); } } function increaseInputVolume() { - setInputVolume(inputVolume + stepVolume) + setInputVolume(inputVolume + stepVolume); } function decreaseInputVolume() { - setInputVolume(inputVolume - stepVolume) + setInputVolume(inputVolume - stepVolume); } function setInputVolume(newVolume: real) { if (source?.ready && source?.audio) { // Clamp it accordingly - source.audio.muted = false - source.audio.volume = Math.max(0, Math.min(Settings.data.audio.volumeOverdrive ? 1.5 : 1.0, newVolume)) + source.audio.muted = false; + source.audio.volume = Math.max(0, Math.min(Settings.data.audio.volumeOverdrive ? 1.5 : 1.0, newVolume)); } else { - Logger.w("AudioService", "No source available") + Logger.w("AudioService", "No source available"); } } function setInputMuted(muted: bool) { if (source?.ready && source?.audio) { - source.audio.muted = muted + source.audio.muted = muted; } else { - Logger.w("AudioService", "No source available") + Logger.w("AudioService", "No source available"); } } function setAudioSink(newSink: PwNode): void { - Pipewire.preferredDefaultAudioSink = newSink + Pipewire.preferredDefaultAudioSink = newSink; // Volume is changed by the sink change - root._volume = newSink?.audio?.volume ?? 0 - root._muted = !!newSink?.audio?.muted + root._volume = newSink?.audio?.volume ?? 0; + root._muted = !!newSink?.audio?.muted; } function setAudioSource(newSource: PwNode): void { - Pipewire.preferredDefaultAudioSource = newSource + Pipewire.preferredDefaultAudioSource = newSource; // The source property will update automatically, which triggers onSourceChanged // which calls updateInputVolume() } function getOutputIcon() { if (muted) { - return "volume-mute" + return "volume-mute"; } - return (volume <= Number.EPSILON) ? "volume-zero" : (volume <= 0.5) ? "volume-low" : "volume-high" + return (volume <= Number.EPSILON) ? "volume-zero" : (volume <= 0.5) ? "volume-low" : "volume-high"; } function getInputIcon() { if (inputMuted) { - return "microphone-mute" + return "microphone-mute"; } - return (inputVolume <= Number.EPSILON) ? "microphone-mute" : "microphone" + return (inputVolume <= Number.EPSILON) ? "microphone-mute" : "microphone"; } } diff --git a/Services/Media/CavaService.qml b/Services/Media/CavaService.qml index ec4810e2..1996b251 100644 --- a/Services/Media/CavaService.qml +++ b/Services/Media/CavaService.qml @@ -9,13 +9,12 @@ import qs.Services.UI Singleton { id: root - /** - * Cava runs if: - * - Bar has an audio visualizer - * - LockScreen is opened - * - A control center is open - */ + * Cava runs if: + * - Bar has an audio visualizer + * - LockScreen is opened + * - A control center is open + */ property bool shouldRun: BarService.hasAudioVisualizer || PanelService.lockScreen?.active || (PanelService.openedPanel && PanelService.openedPanel.panelWrapper.objectName.startsWith("controlCenterPanel")) property var values: Array(barsCount).fill(0) @@ -57,68 +56,68 @@ Singleton { running: root.shouldRun command: ["cava", "-p", "/dev/stdin"] onRunningChanged: { - Logger.d("Cava", "Process running:", running) + Logger.d("Cava", "Process running:", running); } onExited: { - Logger.d("Cava", "Process exited") - stdinEnabled = true - values = Array(barsCount).fill(0) + Logger.d("Cava", "Process exited"); + stdinEnabled = true; + values = Array(barsCount).fill(0); } onStarted: { - Logger.d("Cava", "Process started") + Logger.d("Cava", "Process started"); for (const k in config) { if (typeof config[k] !== "object") { - write(k + "=" + config[k] + "\n") - continue + write(k + "=" + config[k] + "\n"); + continue; } - write("[" + k + "]\n") - const obj = config[k] + write("[" + k + "]\n"); + const obj = config[k]; for (const k2 in obj) { - write(k2 + "=" + obj[k2] + "\n") + write(k2 + "=" + obj[k2] + "\n"); } } - stdinEnabled = false - values = Array(barsCount).fill(0) + stdinEnabled = false; + values = Array(barsCount).fill(0); } stdout: SplitParser { onRead: data => { - const newValues = data.slice(0, -1).split(";").map(v => parseInt(v, 10) / 100) + const newValues = data.slice(0, -1).split(";").map(v => parseInt(v, 10) / 100); // Check if all values are effectively zero (< 0.01) - const allZero = newValues.every(v => v < 0.01) + const allZero = newValues.every(v => v < 0.01); if (allZero) { - root.idleFrameCount++ + root.idleFrameCount++; if (root.idleFrameCount >= root.idleThreshold) { // We're idle - stop updating values to save GPU if (!root.isIdle) { - root.isIdle = true + root.isIdle = true; // Set all values to 0 one final time - root.values = Array(root.barsCount).fill(0) - Logger.d("Cava", "Idle detected - stopped rendering") + root.values = Array(root.barsCount).fill(0); + Logger.d("Cava", "Idle detected - stopped rendering"); } // Don't update values while idle - return + return; } } else { // Audio detected - resume updates - root.idleFrameCount = 0 + root.idleFrameCount = 0; if (root.isIdle) { - root.isIdle = false - Logger.d("Cava", "Audio detected - resumed rendering") + root.isIdle = false; + Logger.d("Cava", "Audio detected - resumed rendering"); } } // Update values only if there's a significant change if (!isIdle) { - root.values = newValues + root.values = newValues; } } } stderr: StdioCollector { onStreamFinished: { if (text.trim()) { - Logger.w("Cava", "Error", text) + Logger.w("Cava", "Error", text); } } } diff --git a/Services/Media/MediaService.qml b/Services/Media/MediaService.qml index a17d9637..172abd42 100644 --- a/Services/Media/MediaService.qml +++ b/Services/Media/MediaService.qml @@ -26,60 +26,60 @@ Singleton { property real infiniteTrackLength: 922337203685 Component.onCompleted: { - updateCurrentPlayer() + updateCurrentPlayer(); } function getAvailablePlayers() { if (!Mpris.players || !Mpris.players.values) { - return [] + return []; } - let allPlayers = Mpris.players.values - let finalPlayers = [] - const genericBrowsers = ["firefox", "chromium", "chrome"] - const blacklist = (Settings.data.audio && Settings.data.audio.mprisBlacklist) ? Settings.data.audio.mprisBlacklist : [] + let allPlayers = Mpris.players.values; + let finalPlayers = []; + const genericBrowsers = ["firefox", "chromium", "chrome"]; + const blacklist = (Settings.data.audio && Settings.data.audio.mprisBlacklist) ? Settings.data.audio.mprisBlacklist : []; // Separate players into specific and generic lists - let specificPlayers = [] - let genericPlayers = [] + let specificPlayers = []; + let genericPlayers = []; for (var i = 0; i < allPlayers.length; i++) { - const identity = String(allPlayers[i].identity || "").toLowerCase() + const identity = String(allPlayers[i].identity || "").toLowerCase(); const match = blacklist.find(b => { - const s = String(b || "").toLowerCase() - return s && (identity.includes(s)) - }) + const s = String(b || "").toLowerCase(); + return s && (identity.includes(s)); + }); if (match) - continue + continue; if (genericBrowsers.some(b => identity.includes(b))) { - genericPlayers.push(allPlayers[i]) + genericPlayers.push(allPlayers[i]); } else { - specificPlayers.push(allPlayers[i]) + specificPlayers.push(allPlayers[i]); } } - let matchedGenericIndices = {} + let matchedGenericIndices = {}; // For each specific player, try to find and pair it with a generic partner for (var i = 0; i < specificPlayers.length; i++) { - let specificPlayer = specificPlayers[i] - let title1 = String(specificPlayer.trackTitle || "").trim() - let wasMatched = false + let specificPlayer = specificPlayers[i]; + let title1 = String(specificPlayer.trackTitle || "").trim(); + let wasMatched = false; if (title1) { for (var j = 0; j < genericPlayers.length; j++) { if (matchedGenericIndices[j]) - continue - let genericPlayer = genericPlayers[j] - let title2 = String(genericPlayer.trackTitle || "").trim() + continue; + let genericPlayer = genericPlayers[j]; + let title2 = String(genericPlayer.trackTitle || "").trim(); if (title2 && (title1.includes(title2) || title2.includes(title1))) { - let dataPlayer = genericPlayer - let identityPlayer = specificPlayer + let dataPlayer = genericPlayer; + let identityPlayer = specificPlayer; - let scoreSpecific = (specificPlayer.trackArtUrl ? 1 : 0) - let scoreGeneric = (genericPlayer.trackArtUrl ? 1 : 0) + let scoreSpecific = (specificPlayer.trackArtUrl ? 1 : 0); + let scoreGeneric = (genericPlayer.trackArtUrl ? 1 : 0); if (scoreSpecific > scoreGeneric) { - dataPlayer = specificPlayer + dataPlayer = specificPlayer; } let virtualPlayer = { @@ -101,171 +101,171 @@ Singleton { "canControl": dataPlayer.canControl || false, "_stateSource": dataPlayer, "_controlTarget": identityPlayer - } - finalPlayers.push(virtualPlayer) - matchedGenericIndices[j] = true - wasMatched = true - break + }; + finalPlayers.push(virtualPlayer); + matchedGenericIndices[j] = true; + wasMatched = true; + break; } } } if (!wasMatched) { - finalPlayers.push(specificPlayer) + finalPlayers.push(specificPlayer); } } // Add any generic players that were not matched for (var i = 0; i < genericPlayers.length; i++) { if (!matchedGenericIndices[i]) { - finalPlayers.push(genericPlayers[i]) + finalPlayers.push(genericPlayers[i]); } } // Filter for controllable players - let controllablePlayers = [] + let controllablePlayers = []; for (var i = 0; i < finalPlayers.length; i++) { - let player = finalPlayers[i] + let player = finalPlayers[i]; if (player && player.canControl) { - controllablePlayers.push(player) + controllablePlayers.push(player); } } - return controllablePlayers + return controllablePlayers; } function findActivePlayer() { - let availablePlayers = getAvailablePlayers() + let availablePlayers = getAvailablePlayers(); if (availablePlayers.length === 0) { //Logger.i("Media", "No active player found") - return null + return null; } // Prioritize the actively playing player --- for (var i = 0; i < availablePlayers.length; i++) { if (availablePlayers[i] && availablePlayers[i].playbackState === MprisPlaybackState.Playing) { - Logger.d("Media", "Found actively playing player: " + availablePlayers[i].identity) - selectedPlayerIndex = i - return availablePlayers[i] + Logger.d("Media", "Found actively playing player: " + availablePlayers[i].identity); + selectedPlayerIndex = i; + return availablePlayers[i]; } } // fallback if nothing is playing) - const preferred = (Settings.data.audio.preferredPlayer || "") + const preferred = (Settings.data.audio.preferredPlayer || ""); if (preferred !== "") { for (var i = 0; i < availablePlayers.length; i++) { - const p = availablePlayers[i] - const identity = String(p.identity || "").toLowerCase() - const pref = preferred.toLowerCase() + const p = availablePlayers[i]; + const identity = String(p.identity || "").toLowerCase(); + const pref = preferred.toLowerCase(); if (identity.includes(pref)) { - selectedPlayerIndex = i - return p + selectedPlayerIndex = i; + return p; } } } if (selectedPlayerIndex < availablePlayers.length) { - return availablePlayers[selectedPlayerIndex] + return availablePlayers[selectedPlayerIndex]; } else { - selectedPlayerIndex = 0 - return availablePlayers[0] + selectedPlayerIndex = 0; + return availablePlayers[0]; } } property bool autoSwitchingPaused: false function switchToPlayer(index) { - let availablePlayers = getAvailablePlayers() + let availablePlayers = getAvailablePlayers(); if (index >= 0 && index < availablePlayers.length) { - let newPlayer = availablePlayers[index] + let newPlayer = availablePlayers[index]; if (newPlayer !== currentPlayer) { - currentPlayer = newPlayer - selectedPlayerIndex = index - currentPosition = currentPlayer ? currentPlayer.position : 0 - Logger.d("Media", "Manually switched to player " + currentPlayer.identity) + currentPlayer = newPlayer; + selectedPlayerIndex = index; + currentPosition = currentPlayer ? currentPlayer.position : 0; + Logger.d("Media", "Manually switched to player " + currentPlayer.identity); } } } // Switch to the most recently active player function updateCurrentPlayer() { - let newPlayer = findActivePlayer() + let newPlayer = findActivePlayer(); if (newPlayer !== currentPlayer) { - currentPlayer = newPlayer - currentPosition = currentPlayer ? currentPlayer.position : 0 - Logger.d("Media", "Switching player") + currentPlayer = newPlayer; + currentPosition = currentPlayer ? currentPlayer.position : 0; + Logger.d("Media", "Switching player"); } } function playPause() { if (currentPlayer) { - let stateSource = currentPlayer._stateSource || currentPlayer - let controlTarget = currentPlayer._controlTarget || currentPlayer + let stateSource = currentPlayer._stateSource || currentPlayer; + let controlTarget = currentPlayer._controlTarget || currentPlayer; if (stateSource.playbackState === MprisPlaybackState.Playing) { - controlTarget.pause() + controlTarget.pause(); } else { - controlTarget.play() + controlTarget.play(); } } } function play() { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target && target.canPlay) { - target.play() + target.play(); } } function stop() { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target) { - target.stop() + target.stop(); } } function pause() { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target && target.canPause) { - target.pause() + target.pause(); } } function next() { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target && target.canGoNext) { - target.next() + target.next(); } } function previous() { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target && target.canGoPrevious) { - target.previous() + target.previous(); } } function seek(position) { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target && target.canSeek) { - target.position = position - currentPosition = position + target.position = position; + currentPosition = position; } } function seekRelative(offset) { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target && target.canSeek && target.length > 0) { - let seekPosition = target.position + offset - target.position = seekPosition - currentPosition = seekPosition + let seekPosition = target.position + offset; + target.position = seekPosition; + currentPosition = seekPosition; } } // Seek to position based on ratio (0.0 to 1.0) function seekByRatio(ratio) { - let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null + let target = currentPlayer ? (currentPlayer._controlTarget || currentPlayer) : null; if (target && target.canSeek && target.length > 0) { - let seekPosition = ratio * target.length - target.position = seekPosition - currentPosition = seekPosition + let seekPosition = ratio * target.length; + target.position = seekPosition; + currentPosition = seekPosition; } } @@ -277,9 +277,9 @@ Singleton { repeat: true onTriggered: { if (currentPlayer && !root.isSeeking && currentPlayer.isPlaying && currentPlayer.playbackState === MprisPlaybackState.Playing) { - currentPosition = currentPlayer.position + currentPosition = currentPlayer.position; } else { - running = false + running = false; } } } @@ -289,12 +289,12 @@ Singleton { target: currentPlayer function onPositionChanged() { if (!root.isSeeking && currentPlayer) { - currentPosition = currentPlayer.position + currentPosition = currentPlayer.position; } } function onPlaybackStateChanged() { if (!root.isSeeking && currentPlayer) { - currentPosition = currentPlayer.position + currentPosition = currentPlayer.position; } } } @@ -302,7 +302,7 @@ Singleton { // Reset position when switching to inactive player onCurrentPlayerChanged: { if (!currentPlayer || !currentPlayer.isPlaying || currentPlayer.playbackState !== MprisPlaybackState.Playing) { - currentPosition = 0 + currentPosition = 0; } } @@ -314,10 +314,10 @@ Singleton { onTriggered: { //Logger.d("MediaService", "playerStateMonitor triggered. autoSwitchingPaused: " + root.autoSwitchingPaused) if (autoSwitchingPaused) - return + return; // Only update if we don't have a playing player or if current player is paused if (!currentPlayer || !currentPlayer.isPlaying || currentPlayer.playbackState !== MprisPlaybackState.Playing) { - updateCurrentPlayer() + updateCurrentPlayer(); } } } @@ -326,8 +326,8 @@ Singleton { Connections { target: Mpris.players function onValuesChanged() { - Logger.d("Media", "Players changed") - updateCurrentPlayer() + Logger.d("Media", "Players changed"); + updateCurrentPlayer(); } } } diff --git a/Services/Media/ScreenRecorderService.qml b/Services/Media/ScreenRecorderService.qml index f8df8e0f..d14aec3a 100644 --- a/Services/Media/ScreenRecorderService.qml +++ b/Services/Media/ScreenRecorderService.qml @@ -27,43 +27,43 @@ Singleton { // Start or Stop recording function toggleRecording() { - (isRecording || isPending) ? stopRecording() : startRecording() + (isRecording || isPending) ? stopRecording() : startRecording(); } // Start screen recording using Quickshell.execDetached function startRecording() { if (!isAvailable) { - return + return; } if (isRecording || isPending) { - return + return; } - isPending = true - hasActiveRecording = false + isPending = true; + hasActiveRecording = false; // Close any opened panel if ((PanelService.openedPanel !== null) && !PanelService.openedPanel.isClosing) { - PanelService.openedPanel.close() + PanelService.openedPanel.close(); } // First, ensure xdg-desktop-portal and a compositor portal are running portalCheckProcess.exec({ - "command": ["sh", "-c", // require core portal AND one of the backends - "pidof xdg-desktop-portal >/dev/null 2>&1 && (pidof xdg-desktop-portal-wlr >/dev/null 2>&1 || pidof xdg-desktop-portal-hyprland >/dev/null 2>&1 || pidof xdg-desktop-portal-gnome >/dev/null 2>&1 || pidof xdg-desktop-portal-kde >/dev/null 2>&1)"] - }) + "command": ["sh", "-c" // require core portal AND one of the backends + , "pidof xdg-desktop-portal >/dev/null 2>&1 && (pidof xdg-desktop-portal-wlr >/dev/null 2>&1 || pidof xdg-desktop-portal-hyprland >/dev/null 2>&1 || pidof xdg-desktop-portal-gnome >/dev/null 2>&1 || pidof xdg-desktop-portal-kde >/dev/null 2>&1)"] + }); } function launchRecorder() { - var filename = Time.getFormattedTimestamp() + ".mp4" - var videoDir = Settings.preprocessPath(settings.directory) + var filename = Time.getFormattedTimestamp() + ".mp4"; + var videoDir = Settings.preprocessPath(settings.directory); if (videoDir && !videoDir.endsWith("/")) { - videoDir += "/" + videoDir += "/"; } - outputPath = videoDir + filename + outputPath = videoDir + filename; - var audioArg = (settings.audioSource === "both") ? `-a "default_output|default_input"` : `-a ${settings.audioSource}` + var audioArg = (settings.audioSource === "both") ? `-a "default_output|default_input"` : `-a ${settings.audioSource}`; - var flags = `-w ${settings.videoSource} -f ${settings.frameRate} -ac ${settings.audioCodec} -k ${settings.videoCodec} ${audioArg} -q ${settings.quality} -cursor ${settings.showCursor ? "yes" : "no"} -cr ${settings.colorRange} -o "${outputPath}"` + var flags = `-w ${settings.videoSource} -f ${settings.frameRate} -ac ${settings.audioCodec} -k ${settings.videoCodec} ${audioArg} -q ${settings.quality} -cursor ${settings.showCursor ? "yes" : "no"} -cr ${settings.colorRange} -o "${outputPath}"`; var command = ` _gpuscreenrecorder_flatpak_installed() { flatpak list --app | grep -q "com.dec05eba.gpu_screen_recorder" @@ -74,35 +74,35 @@ Singleton { flatpak run --command=gpu-screen-recorder --file-forwarding com.dec05eba.gpu_screen_recorder ${flags} else echo "GPU_SCREEN_RECORDER_NOT_INSTALLED" - fi` + fi`; // Use Process instead of execDetached so we can monitor it and read stderr recorderProcess.exec({ "command": ["sh", "-c", command] - }) + }); // Start monitoring - if process ends quickly, it was likely cancelled - pendingTimer.running = true + pendingTimer.running = true; } // Stop recording using Quickshell.execDetached function stopRecording() { if (!isRecording && !isPending) { - return + return; } - ToastService.showNotice(I18n.tr("toast.recording.stopping"), outputPath, "settings-screen-recorder") + ToastService.showNotice(I18n.tr("toast.recording.stopping"), outputPath, "settings-screen-recorder"); - Quickshell.execDetached(["sh", "-c", "pkill -SIGINT -f 'gpu-screen-recorder' || pkill -SIGINT -f 'com.dec05eba.gpu_screen_recorder'"]) + Quickshell.execDetached(["sh", "-c", "pkill -SIGINT -f 'gpu-screen-recorder' || pkill -SIGINT -f 'com.dec05eba.gpu_screen_recorder'"]); - isRecording = false - isPending = false - pendingTimer.running = false - monitorTimer.running = false - hasActiveRecording = false + isRecording = false; + isPending = false; + pendingTimer.running = false; + monitorTimer.running = false; + hasActiveRecording = false; // Just in case, force kill after 3 seconds - killTimer.running = true + killTimer.running = true; } // Process to run and monitor gpu-screen-recorder @@ -113,37 +113,37 @@ Singleton { onExited: function (exitCode, exitStatus) { if (isPending) { // Process ended while we were pending - likely cancelled or error - isPending = false - pendingTimer.running = false + isPending = false; + pendingTimer.running = false; // Check if gpu-screen-recorder is not installed - const stdout = String(recorderProcess.stdout.text || "").trim() + const stdout = String(recorderProcess.stdout.text || "").trim(); if (stdout === "GPU_SCREEN_RECORDER_NOT_INSTALLED") { - ToastService.showError(I18n.tr("toast.recording.not-installed"), I18n.tr("toast.recording.not-installed-desc")) - return + ToastService.showError(I18n.tr("toast.recording.not-installed"), I18n.tr("toast.recording.not-installed-desc")); + return; } // If it failed to start, show a clear error toast with stderr if (exitCode !== 0) { - const err = String(recorderProcess.stderr.text || "").trim() + const err = String(recorderProcess.stderr.text || "").trim(); if (err.length > 0) - ToastService.showError(I18n.tr("toast.recording.failed-start"), err) + ToastService.showError(I18n.tr("toast.recording.failed-start"), err); else - ToastService.showError(I18n.tr("toast.recording.failed-start"), I18n.tr("toast.recording.failed-gpu")) + ToastService.showError(I18n.tr("toast.recording.failed-start"), I18n.tr("toast.recording.failed-gpu")); } } else if (isRecording) { // Process ended normally while recording - isRecording = false - monitorTimer.running = false + isRecording = false; + monitorTimer.running = false; // Consider successful save if exitCode == 0 if (exitCode === 0) { - ToastService.showNotice(I18n.tr("toast.recording.saved"), outputPath, "settings-screen-recorder") + ToastService.showNotice(I18n.tr("toast.recording.saved"), outputPath, "settings-screen-recorder"); } else { - const err2 = String(recorderProcess.stderr.text || "").trim() + const err2 = String(recorderProcess.stderr.text || "").trim(); if (err2.length > 0) - ToastService.showError(I18n.tr("toast.recording.failed-start"), err2) + ToastService.showError(I18n.tr("toast.recording.failed-start"), err2); else - ToastService.showError(I18n.tr("toast.recording.failed-start"), I18n.tr("toast.recording.failed-general")) + ToastService.showError(I18n.tr("toast.recording.failed-start"), I18n.tr("toast.recording.failed-general")); } } } @@ -155,11 +155,11 @@ Singleton { onExited: function (exitCode, exitStatus) { if (exitCode === 0) { // Portals available, proceed to launch - launchRecorder() + launchRecorder(); } else { - isPending = false - hasActiveRecording = false - ToastService.showError(I18n.tr("toast.recording.no-portals"), I18n.tr("toast.recording.no-portals-desc")) + isPending = false; + hasActiveRecording = false; + ToastService.showError(I18n.tr("toast.recording.no-portals"), I18n.tr("toast.recording.no-portals-desc")); } } } @@ -172,14 +172,14 @@ Singleton { onTriggered: { if (isPending && recorderProcess.running) { // Process is still running after 2 seconds - assume recording started successfully - isPending = false - isRecording = true - hasActiveRecording = true - monitorTimer.running = true + isPending = false; + isRecording = true; + hasActiveRecording = true; + monitorTimer.running = true; // Don't show a toast when recording starts to avoid having the toast in every video. } else if (isPending) { // Process not running anymore - was cancelled or failed - isPending = false + isPending = false; } } } @@ -192,8 +192,8 @@ Singleton { repeat: true onTriggered: { if (!recorderProcess.running && isRecording) { - isRecording = false - running = false + isRecording = false; + running = false; } } } @@ -204,7 +204,7 @@ Singleton { running: false repeat: false onTriggered: { - Quickshell.execDetached(["sh", "-c", "pkill -9 -f 'gpu-screen-recorder' 2>/dev/null || pkill -9 -f 'com.dec05eba.gpu_screen_recorder' 2>/dev/null || true"]) + Quickshell.execDetached(["sh", "-c", "pkill -9 -f 'gpu-screen-recorder' 2>/dev/null || pkill -9 -f 'com.dec05eba.gpu_screen_recorder' 2>/dev/null || true"]); } } } diff --git a/Services/Networking/BluetoothService.qml b/Services/Networking/BluetoothService.qml index 4a7f8745..faba2a2b 100644 --- a/Services/Networking/BluetoothService.qml +++ b/Services/Networking/BluetoothService.qml @@ -21,30 +21,30 @@ Singleton { readonly property var devices: adapter ? adapter.devices : null readonly property var pairedDevices: { if (!adapter || !adapter.devices) { - return [] + return []; } return adapter.devices.values.filter(dev => { - return dev && (dev.paired || dev.trusted) - }) + return dev && (dev.paired || dev.trusted); + }); } readonly property var connectedDevices: { if (!adapter || !adapter.devices) { - return [] + return []; } - return adapter.devices.values.filter(dev => dev && dev.connected) + return adapter.devices.values.filter(dev => dev && dev.connected); } readonly property var allDevicesWithBattery: { if (!adapter || !adapter.devices) { - return [] + return []; } return adapter.devices.values.filter(dev => { - return dev && dev.batteryAvailable && dev.battery > 0 - }) + return dev && dev.batteryAvailable && dev.battery > 0; + }); } function init() { - Logger.i("Bluetooth", "Service started") + Logger.i("Bluetooth", "Service started"); } Timer { @@ -58,198 +58,197 @@ Singleton { target: adapter function onStateChanged() { if (!adapter) { - Logger.w("Bluetooth", "onStateChanged", "No adapter available") - return + Logger.w("Bluetooth", "onStateChanged", "No adapter available"); + return; } if (adapter.state === BluetoothAdapterState.Enabling || adapter.state === BluetoothAdapterState.Disabling) { - return + return; } - Logger.d("Bluetooth", "onStateChanged", adapter.state) - const bluetoothBlockedToggled = (root.blocked !== lastBluetoothBlocked) - root.lastBluetoothBlocked = root.blocked + Logger.d("Bluetooth", "onStateChanged", adapter.state); + const bluetoothBlockedToggled = (root.blocked !== lastBluetoothBlocked); + root.lastBluetoothBlocked = root.blocked; if (bluetoothBlockedToggled) { - checkWifiBlocked.running = true + checkWifiBlocked.running = true; } else if (adapter.enabled) { - ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.enabled"), "bluetooth") - discoveryTimer.running = true + ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.enabled"), "bluetooth"); + discoveryTimer.running = true; } else { - ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.disabled"), "bluetooth-off") + ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.disabled"), "bluetooth-off"); } } } function sortDevices(devices) { return devices.sort((a, b) => { - var aName = a.name || a.deviceName || "" - var bName = b.name || b.deviceName || "" + var aName = a.name || a.deviceName || ""; + var bName = b.name || b.deviceName || ""; - var aHasRealName = aName.includes(" ") && aName.length > 3 - var bHasRealName = bName.includes(" ") && bName.length > 3 + var aHasRealName = aName.includes(" ") && aName.length > 3; + var bHasRealName = bName.includes(" ") && bName.length > 3; if (aHasRealName && !bHasRealName) - return -1 + return -1; if (!aHasRealName && bHasRealName) - return 1 + return 1; - var aSignal = (a.signalStrength !== undefined && a.signalStrength > 0) ? a.signalStrength : 0 - var bSignal = (b.signalStrength !== undefined && b.signalStrength > 0) ? b.signalStrength : 0 - return bSignal - aSignal - }) + var aSignal = (a.signalStrength !== undefined && a.signalStrength > 0) ? a.signalStrength : 0; + var bSignal = (b.signalStrength !== undefined && b.signalStrength > 0) ? b.signalStrength : 0; + return bSignal - aSignal; + }); } function getDeviceIcon(device) { if (!device) { - return "bt-device-generic" + return "bt-device-generic"; } - var name = (device.name || device.deviceName || "").toLowerCase() - var icon = (device.icon || "").toLowerCase() + var name = (device.name || device.deviceName || "").toLowerCase(); + var icon = (device.icon || "").toLowerCase(); if (icon.includes("headset") || icon.includes("audio") || name.includes("headphone") || name.includes("airpod") || name.includes("headset") || name.includes("arctis")) { - return "bt-device-headphones" + return "bt-device-headphones"; } if (icon.includes("mouse") || name.includes("mouse")) { - return "bt-device-mouse" + return "bt-device-mouse"; } if (icon.includes("keyboard") || name.includes("keyboard")) { - return "bt-device-keyboard" + return "bt-device-keyboard"; } if (icon.includes("phone") || name.includes("phone") || name.includes("iphone") || name.includes("android") || name.includes("samsung")) { - return "bt-device-phone" + return "bt-device-phone"; } if (icon.includes("watch") || name.includes("watch")) { - return "bt-device-watch" + return "bt-device-watch"; } if (icon.includes("speaker") || name.includes("speaker")) { - return "bt-device-speaker" + return "bt-device-speaker"; } if (icon.includes("display") || name.includes("tv")) { - return "bt-device-tv" + return "bt-device-tv"; } - return "bt-device-generic" + return "bt-device-generic"; } function canConnect(device) { if (!device) - return false - + return false; /* - Paired - Means you’ve successfully exchanged keys with the device. - The devices remember each other and can authenticate without repeating the pairing process. - Example: once your headphones are paired, you don’t need to type a PIN every time. - Hence, instead of !device.paired, should be device.connected + Paired + Means you’ve successfully exchanged keys with the device. + The devices remember each other and can authenticate without repeating the pairing process. + Example: once your headphones are paired, you don’t need to type a PIN every time. + Hence, instead of !device.paired, should be device.connected */ - return !device.connected && !device.pairing && !device.blocked + return !device.connected && !device.pairing && !device.blocked; } function canDisconnect(device) { if (!device) - return false - return device.connected && !device.pairing && !device.blocked + return false; + return device.connected && !device.pairing && !device.blocked; } function getStatusString(device) { if (device.state === BluetoothDeviceState.Connecting) { - return "Connecting..." + return "Connecting..."; } if (device.pairing) { - return "Pairing..." + return "Pairing..."; } if (device.blocked) { - return "Blocked" + return "Blocked"; } - return "" + return ""; } function getSignalStrength(device) { if (!device || device.signalStrength === undefined || device.signalStrength <= 0) { - return "Signal: Unknown" + return "Signal: Unknown"; } - var signal = device.signalStrength + var signal = device.signalStrength; if (signal >= 80) { - return "Signal: Excellent" + return "Signal: Excellent"; } if (signal >= 60) { - return "Signal: Good" + return "Signal: Good"; } if (signal >= 40) { - return "Signal: Fair" + return "Signal: Fair"; } if (signal >= 20) { - return "Signal: Poor" + return "Signal: Poor"; } - return "Signal: Very poor" + return "Signal: Very poor"; } function getBattery(device) { - return `Battery: ${Math.round(device.battery * 100)}%` + return `Battery: ${Math.round(device.battery * 100)}%`; } function getSignalIcon(device) { if (!device || device.signalStrength === undefined || device.signalStrength <= 0) { - return "antenna-bars-off" + return "antenna-bars-off"; } - var signal = device.signalStrength + var signal = device.signalStrength; if (signal >= 80) { - return "antenna-bars-5" + return "antenna-bars-5"; } if (signal >= 60) { - return "antenna-bars-4" + return "antenna-bars-4"; } if (signal >= 40) { - return "antenna-bars-3" + return "antenna-bars-3"; } if (signal >= 20) { - return "antenna-bars-2" + return "antenna-bars-2"; } - return "antenna-bars-1" + return "antenna-bars-1"; } function isDeviceBusy(device) { if (!device) { - return false + return false; } - return device.pairing || device.state === BluetoothDeviceState.Disconnecting || device.state === BluetoothDeviceState.Connecting + return device.pairing || device.state === BluetoothDeviceState.Disconnecting || device.state === BluetoothDeviceState.Connecting; } function connectDeviceWithTrust(device) { if (!device) { - return + return; } - device.trusted = true - device.connect() + device.trusted = true; + device.connect(); } function disconnectDevice(device) { if (!device) { - return + return; } - device.disconnect() + device.disconnect(); } function forgetDevice(device) { if (!device) { - return + return; } - device.trusted = false - device.forget() + device.trusted = false; + device.forget(); } function setBluetoothEnabled(state) { if (!adapter) { - Logger.w("Bluetooth", "No adapter available") - return + Logger.w("Bluetooth", "No adapter available"); + return; } - Logger.i("Bluetooth", "SetBluetoothEnabled", state) - adapter.enabled = state + Logger.i("Bluetooth", "SetBluetoothEnabled", state); + adapter.enabled = state; } Process { @@ -259,25 +258,25 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const wifiBlocked = text && text.trim().includes("Soft blocked: yes") - Logger.d("Network", "Wi-Fi adapter was detected as blocked:", blocked) + const wifiBlocked = text && text.trim().includes("Soft blocked: yes"); + Logger.d("Network", "Wi-Fi adapter was detected as blocked:", blocked); // Check if airplane mode has been toggled if (wifiBlocked && wifiBlocked === root.blocked) { - root.airplaneModeToggled = true - NetworkService.setWifiEnabled(false) - ToastService.showNotice(I18n.tr("toast.airplane-mode.title"), I18n.tr("toast.airplane-mode.enabled"), "plane") + root.airplaneModeToggled = true; + NetworkService.setWifiEnabled(false); + ToastService.showNotice(I18n.tr("toast.airplane-mode.title"), I18n.tr("toast.airplane-mode.enabled"), "plane"); } else if (!wifiBlocked && wifiBlocked === root.blocked) { - root.airplaneModeToggled = true - NetworkService.setWifiEnabled(true) - ToastService.showNotice(I18n.tr("toast.airplane-mode.title"), I18n.tr("toast.airplane-mode.disabled"), "plane-off") + root.airplaneModeToggled = true; + NetworkService.setWifiEnabled(true); + ToastService.showNotice(I18n.tr("toast.airplane-mode.title"), I18n.tr("toast.airplane-mode.disabled"), "plane-off"); } else if (adapter.enabled) { - ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.enabled"), "bluetooth") - discoveryTimer.running = true + ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.enabled"), "bluetooth"); + discoveryTimer.running = true; } else { - ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.disabled"), "bluetooth-off") + ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.disabled"), "bluetooth-off"); } - root.airplaneModeToggled = false + root.airplaneModeToggled = false; } } } diff --git a/Services/Networking/NetworkService.qml b/Services/Networking/NetworkService.qml index 543a9954..e4b881b4 100644 --- a/Services/Networking/NetworkService.qml +++ b/Services/Networking/NetworkService.qml @@ -41,8 +41,8 @@ Singleton { } onLoadFailed: { - cacheAdapter.knownNetworks = ({}) - cacheAdapter.lastConnected = "" + cacheAdapter.knownNetworks = ({}); + cacheAdapter.lastConnected = ""; } } @@ -51,25 +51,25 @@ Singleton { function onWifiEnabledChanged() { if (Settings.data.network.wifiEnabled) { if (!BluetoothService.airplaneModeToggled) { - ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.enabled"), "wifi") + ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.enabled"), "wifi"); } // Perform a scan to update the UI - delayedScanTimer.interval = 3000 - delayedScanTimer.restart() + delayedScanTimer.interval = 3000; + delayedScanTimer.restart(); } else { if (!BluetoothService.airplaneModeToggled) { - ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.disabled"), "wifi-off") + ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.disabled"), "wifi-off"); } // Clear networks so the widget icon changes - root.networks = ({}) + root.networks = ({}); } } } Component.onCompleted: { - Logger.i("Network", "Service started") - syncWifiState() - scan() + Logger.i("Network", "Service started"); + syncWifiState(); + scan(); } // Save cache with debounce @@ -80,7 +80,7 @@ Singleton { } function saveCache() { - saveDebounce.restart() + saveDebounce.restart(); } // Delayed scan timer @@ -112,98 +112,96 @@ Singleton { // Core functions function syncWifiState() { - wifiStateProcess.running = true + wifiStateProcess.running = true; } function setWifiEnabled(enabled) { - Settings.data.network.wifiEnabled = enabled - wifiStateEnableProcess.running = true + Settings.data.network.wifiEnabled = enabled; + wifiStateEnableProcess.running = true; } function scan() { if (!Settings.data.network.wifiEnabled) - return - + return; if (scanning) { // Mark current scan results to be ignored and schedule a new scan - Logger.d("Network", "Scan already in progress, will ignore results and rescan") - ignoreScanResults = true - scanPending = true - return + Logger.d("Network", "Scan already in progress, will ignore results and rescan"); + ignoreScanResults = true; + scanPending = true; + return; } - scanning = true - lastError = "" - ignoreScanResults = false + scanning = true; + lastError = ""; + ignoreScanResults = false; // Get existing profiles first, then scan - profileCheckProcess.running = true - Logger.d("Network", "Wi-Fi scan in progress...") + profileCheckProcess.running = true; + Logger.d("Network", "Wi-Fi scan in progress..."); } function connect(ssid, password = "") { if (connecting) - return - - connecting = true - connectingTo = ssid - lastError = "" + return; + connecting = true; + connectingTo = ssid; + lastError = ""; // Check if we have a saved connection if (networks[ssid]?.existing || cachedNetworks[ssid]) { - connectProcess.mode = "saved" - connectProcess.ssid = ssid - connectProcess.password = "" + connectProcess.mode = "saved"; + connectProcess.ssid = ssid; + connectProcess.password = ""; } else { - connectProcess.mode = "new" - connectProcess.ssid = ssid - connectProcess.password = password + connectProcess.mode = "new"; + connectProcess.ssid = ssid; + connectProcess.password = password; } - connectProcess.running = true + connectProcess.running = true; } function disconnect(ssid) { - disconnectingFrom = ssid - disconnectProcess.ssid = ssid - disconnectProcess.running = true + disconnectingFrom = ssid; + disconnectProcess.ssid = ssid; + disconnectProcess.running = true; } function forget(ssid) { - forgettingNetwork = ssid + forgettingNetwork = ssid; // Remove from cache - let known = cacheAdapter.knownNetworks - delete known[ssid] - cacheAdapter.knownNetworks = known + let known = cacheAdapter.knownNetworks; + delete known[ssid]; + cacheAdapter.knownNetworks = known; if (cacheAdapter.lastConnected === ssid) { - cacheAdapter.lastConnected = "" + cacheAdapter.lastConnected = ""; } - saveCache() + saveCache(); // Remove from system - forgetProcess.ssid = ssid - forgetProcess.running = true + forgetProcess.ssid = ssid; + forgetProcess.running = true; } // Helper function to immediately update network status function updateNetworkStatus(ssid, connected) { - let nets = networks + let nets = networks; // Update all networks connected status for (let key in nets) { if (nets[key].connected && key !== ssid) { - nets[key].connected = false + nets[key].connected = false; } } // Update the target network if it exists if (nets[ssid]) { - nets[ssid].connected = connected - nets[ssid].existing = true - nets[ssid].cached = true + nets[ssid].connected = connected; + nets[ssid].existing = true; + nets[ssid].cached = true; } else if (connected) { // Create a temporary entry if network doesn't exist yet nets[ssid] = { @@ -213,29 +211,29 @@ Singleton { "connected": true, "existing": true, "cached": true - } + }; } // Trigger property change notification - networks = ({}) - networks = nets + networks = ({}); + networks = nets; } // Helper functions function signalIcon(signal, isConnected = false) { if (isConnected && !root.internetConnectivity) - return "world-off" + return "world-off"; if (signal >= 80) - return "wifi" + return "wifi"; if (signal >= 50) - return "wifi-2" + return "wifi-2"; if (signal >= 20) - return "wifi-1" - return "wifi-0" + return "wifi-1"; + return "wifi-0"; } function isSecured(security) { - return security && security !== "--" && security.trim() !== "" + return security && security !== "--" && security.trim() !== ""; } // Processes @@ -247,12 +245,12 @@ Singleton { stdout: StdioCollector { onStreamFinished: { const connected = text.split("\n").some(line => { - const parts = line.split(":") - return parts[1] === "ethernet" && parts[2] === "connected" - }) + const parts = line.split(":"); + return parts[1] === "ethernet" && parts[2] === "connected"; + }); if (root.ethernetConnected !== connected) { - root.ethernetConnected = connected - Logger.d("Network", "Ethernet connected:", root.ethernetConnected) + root.ethernetConnected = connected; + Logger.d("Network", "Ethernet connected:", root.ethernetConnected); } } } @@ -267,10 +265,10 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const enabled = text.trim() === "enabled" - Logger.d("Network", "Wi-Fi adapter was detect as enabled:", enabled) + const enabled = text.trim() === "enabled"; + Logger.d("Network", "Wi-Fi adapter was detect as enabled:", enabled); if (Settings.data.network.wifiEnabled !== enabled) { - Settings.data.network.wifiEnabled = enabled + Settings.data.network.wifiEnabled = enabled; } } } @@ -284,16 +282,16 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - Logger.i("Network", "Wi-Fi state change command executed.") + Logger.i("Network", "Wi-Fi state change command executed."); // Re-check the state to ensure it's in sync - syncWifiState() + syncWifiState(); } } stderr: StdioCollector { onStreamFinished: { if (text.trim()) { - Logger.w("Network", "Error changing Wi-Fi state: " + text) + Logger.w("Network", "Error changing Wi-Fi state: " + text); } } } @@ -309,35 +307,35 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const result = text.trim() + const result = text.trim(); if (!result) { - return + return; } if (result === "none" && root.networkConnectivity !== result) { - root.networkConnectivity = result - connectivityCheckProcess.failedChecks = 0 - root.scan() + root.networkConnectivity = result; + connectivityCheckProcess.failedChecks = 0; + root.scan(); } if (result === "full" && root.networkConnectivity !== result) { - root.networkConnectivity = result - root.internetConnectivity = true - connectivityCheckProcess.failedChecks = 0 - root.scan() + root.networkConnectivity = result; + root.internetConnectivity = true; + connectivityCheckProcess.failedChecks = 0; + root.scan(); } if ((result === "limited" || result === "portal") && root.networkConnectivity !== result) { - connectivityCheckProcess.failedChecks++ + connectivityCheckProcess.failedChecks++; if (connectivityCheckProcess.failedChecks === 3) { - root.networkConnectivity = result - pingCheckProcess.running = true + root.networkConnectivity = result; + pingCheckProcess.running = true; } } if (result === "unknown" && root.networkConnectivity !== result) { - root.networkConnectivity = result - connectivityCheckProcess.failedChecks = 0 + root.networkConnectivity = result; + connectivityCheckProcess.failedChecks = 0; } } } @@ -345,7 +343,7 @@ Singleton { stderr: StdioCollector { onStreamFinished: { if (text.trim()) { - Logger.w("Network", "Connectivity check error: " + text) + Logger.w("Network", "Connectivity check error: " + text); } } } @@ -357,14 +355,14 @@ Singleton { onExited: (exitCode, exitStatus) => { if (exitCode === 0) { - connectivityCheckProcess.failedChecks = 0 + connectivityCheckProcess.failedChecks = 0; } else { - root.internetConnectivity = false - Logger.i("Network", "No internet connectivity") - ToastService.showWarning(root.cachedLastConnected, I18n.tr("toast.internet.limited")) - connectivityCheckProcess.failedChecks = 0 + root.internetConnectivity = false; + Logger.i("Network", "No internet connectivity"); + ToastService.showWarning(root.cachedLastConnected, I18n.tr("toast.internet.limited")); + connectivityCheckProcess.failedChecks = 0; } - root.scan() + root.scan(); } } @@ -377,25 +375,25 @@ Singleton { stdout: StdioCollector { onStreamFinished: { if (root.ignoreScanResults) { - Logger.d("Network", "Ignoring profile check results (new scan requested)") - root.scanning = false + Logger.d("Network", "Ignoring profile check results (new scan requested)"); + root.scanning = false; // Check if we need to start a new scan if (root.scanPending) { - root.scanPending = false - delayedScanTimer.interval = 100 - delayedScanTimer.restart() + root.scanPending = false; + delayedScanTimer.interval = 100; + delayedScanTimer.restart(); } - return + return; } - const profiles = {} - const lines = text.split("\n").filter(l => l.trim()) + const profiles = {}; + const lines = text.split("\n").filter(l => l.trim()); for (const line of lines) { - profiles[line.trim()] = true + profiles[line.trim()] = true; } - scanProcess.existingProfiles = profiles - scanProcess.running = true + scanProcess.existingProfiles = profiles; + scanProcess.running = true; } } } @@ -410,65 +408,65 @@ Singleton { stdout: StdioCollector { onStreamFinished: { if (root.ignoreScanResults) { - Logger.d("Network", "Ignoring scan results (new scan requested)") - root.scanning = false + Logger.d("Network", "Ignoring scan results (new scan requested)"); + root.scanning = false; // Check if we need to start a new scan if (root.scanPending) { - root.scanPending = false - delayedScanTimer.interval = 100 - delayedScanTimer.restart() + root.scanPending = false; + delayedScanTimer.interval = 100; + delayedScanTimer.restart(); } - return + return; } // Process the scan results as before... - const lines = text.split("\n") - const networksMap = {} + const lines = text.split("\n"); + const networksMap = {}; for (var i = 0; i < lines.length; ++i) { - const line = lines[i].trim() + const line = lines[i].trim(); if (!line) - continue + continue; // Parse from the end to handle SSIDs with colons // Format is SSID:SECURITY:SIGNAL:IN-USE // We know the last 3 fields, so everything else is SSID - const lastColonIdx = line.lastIndexOf(":") + const lastColonIdx = line.lastIndexOf(":"); if (lastColonIdx === -1) { - Logger.w("Network", "Malformed nmcli output line:", line) - continue + Logger.w("Network", "Malformed nmcli output line:", line); + continue; } - const inUse = line.substring(lastColonIdx + 1) - const remainingLine = line.substring(0, lastColonIdx) + const inUse = line.substring(lastColonIdx + 1); + const remainingLine = line.substring(0, lastColonIdx); - const secondLastColonIdx = remainingLine.lastIndexOf(":") + const secondLastColonIdx = remainingLine.lastIndexOf(":"); if (secondLastColonIdx === -1) { - Logger.w("Network", "Malformed nmcli output line:", line) - continue + Logger.w("Network", "Malformed nmcli output line:", line); + continue; } - const signal = remainingLine.substring(secondLastColonIdx + 1) - const remainingLine2 = remainingLine.substring(0, secondLastColonIdx) + const signal = remainingLine.substring(secondLastColonIdx + 1); + const remainingLine2 = remainingLine.substring(0, secondLastColonIdx); - const thirdLastColonIdx = remainingLine2.lastIndexOf(":") + const thirdLastColonIdx = remainingLine2.lastIndexOf(":"); if (thirdLastColonIdx === -1) { - Logger.w("Network", "Malformed nmcli output line:", line) - continue + Logger.w("Network", "Malformed nmcli output line:", line); + continue; } - const security = remainingLine2.substring(thirdLastColonIdx + 1) - const ssid = remainingLine2.substring(0, thirdLastColonIdx) + const security = remainingLine2.substring(thirdLastColonIdx + 1); + const ssid = remainingLine2.substring(0, thirdLastColonIdx); if (ssid) { - const signalInt = parseInt(signal) || 0 - const connected = inUse === "*" + const signalInt = parseInt(signal) || 0; + const connected = inUse === "*"; // Track connected network in cache if (connected && cacheAdapter.lastConnected !== ssid) { - cacheAdapter.lastConnected = ssid - saveCache() + cacheAdapter.lastConnected = ssid; + saveCache(); } if (!networksMap[ssid]) { @@ -479,59 +477,59 @@ Singleton { "connected": connected, "existing": ssid in scanProcess.existingProfiles, "cached": ssid in cacheAdapter.knownNetworks - } + }; } else { // Keep the best signal for duplicate SSIDs - const existingNet = networksMap[ssid] + const existingNet = networksMap[ssid]; if (connected) { - existingNet.connected = true + existingNet.connected = true; } if (signalInt > existingNet.signal) { - existingNet.signal = signalInt - existingNet.security = security || "--" + existingNet.signal = signalInt; + existingNet.security = security || "--"; } } } } // Logging - const oldSSIDs = Object.keys(root.networks) - const newSSIDs = Object.keys(networksMap) - const newNetworks = newSSIDs.filter(ssid => !oldSSIDs.includes(ssid)) - const lostNetworks = oldSSIDs.filter(ssid => !newSSIDs.includes(ssid)) + const oldSSIDs = Object.keys(root.networks); + const newSSIDs = Object.keys(networksMap); + const newNetworks = newSSIDs.filter(ssid => !oldSSIDs.includes(ssid)); + const lostNetworks = oldSSIDs.filter(ssid => !newSSIDs.includes(ssid)); if (newNetworks.length > 0 || lostNetworks.length > 0) { if (newNetworks.length > 0) { - Logger.d("Network", "New Wi-Fi SSID discovered:", newNetworks.join(", ")) + Logger.d("Network", "New Wi-Fi SSID discovered:", newNetworks.join(", ")); } if (lostNetworks.length > 0) { - Logger.d("Network", "Wi-Fi SSID disappeared:", lostNetworks.join(", ")) + Logger.d("Network", "Wi-Fi SSID disappeared:", lostNetworks.join(", ")); } - Logger.d("Network", "Total Wi-Fi SSIDs:", Object.keys(networksMap).length) + Logger.d("Network", "Total Wi-Fi SSIDs:", Object.keys(networksMap).length); } - Logger.d("Network", "Wi-Fi scan completed") - root.networks = networksMap - root.scanning = false + Logger.d("Network", "Wi-Fi scan completed"); + root.networks = networksMap; + root.scanning = false; // Check if we need to start a new scan if (root.scanPending) { - root.scanPending = false - delayedScanTimer.interval = 100 - delayedScanTimer.restart() + root.scanPending = false; + delayedScanTimer.interval = 100; + delayedScanTimer.restart(); } } } stderr: StdioCollector { onStreamFinished: { - root.scanning = false + root.scanning = false; if (text.trim()) { - Logger.w("Network", "Scan error: " + text) + Logger.w("Network", "Scan error: " + text); // If scan fails, retry - delayedScanTimer.interval = 5000 - delayedScanTimer.restart() + delayedScanTimer.interval = 5000; + delayedScanTimer.restart(); } } } @@ -545,13 +543,13 @@ Singleton { command: { if (mode === "saved") { - return ["nmcli", "connection", "up", "id", ssid] + return ["nmcli", "connection", "up", "id", ssid]; } else { - const cmd = ["nmcli", "device", "wifi", "connect", ssid] + const cmd = ["nmcli", "device", "wifi", "connect", ssid]; if (password) { - cmd.push("password", password) + cmd.push("password", password); } - return cmd + return cmd; } } environment: ({ @@ -563,59 +561,59 @@ Singleton { // Check if the output actually indicates success // nmcli outputs "Device '...' successfully activated" or "Connection successfully activated" // on success. Empty output or other messages indicate failure. - const output = text.trim() + const output = text.trim(); if (!output || (!output.includes("successfully activated") && !output.includes("Connection successfully"))) { // No success message - likely an error occurred // Don't update anything, let stderr handler deal with it - return + return; } // Success - update cache - let known = cacheAdapter.knownNetworks + let known = cacheAdapter.knownNetworks; known[connectProcess.ssid] = { "profileName": connectProcess.ssid, "lastConnected": Date.now() - } - cacheAdapter.knownNetworks = known - cacheAdapter.lastConnected = connectProcess.ssid - saveCache() + }; + cacheAdapter.knownNetworks = known; + cacheAdapter.lastConnected = connectProcess.ssid; + saveCache(); // Immediately update the UI before scanning - root.updateNetworkStatus(connectProcess.ssid, true) + root.updateNetworkStatus(connectProcess.ssid, true); - root.connecting = false - root.connectingTo = "" - Logger.i("Network", `Connected to network: '${connectProcess.ssid}'`) + root.connecting = false; + root.connectingTo = ""; + Logger.i("Network", `Connected to network: '${connectProcess.ssid}'`); ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.connected", { "ssid": connectProcess.ssid - }), "wifi") + }), "wifi"); // Still do a scan to get accurate signal and security info - delayedScanTimer.interval = 5000 - delayedScanTimer.restart() + delayedScanTimer.interval = 5000; + delayedScanTimer.restart(); } } stderr: StdioCollector { onStreamFinished: { - root.connecting = false - root.connectingTo = "" + root.connecting = false; + root.connectingTo = ""; if (text.trim()) { // Parse common errors if (text.includes("Secrets were required") || text.includes("no secrets provided")) { - root.lastError = "Incorrect password" - forget(connectProcess.ssid) + root.lastError = "Incorrect password"; + forget(connectProcess.ssid); } else if (text.includes("No network with SSID")) { - root.lastError = "Network not found" + root.lastError = "Network not found"; } else if (text.includes("Timeout")) { - root.lastError = "Connection timeout" + root.lastError = "Connection timeout"; } else { - root.lastError = text.split("\n")[0].trim() + root.lastError = text.split("\n")[0].trim(); } - Logger.w("Network", "Connect error: " + text) + Logger.w("Network", "Connect error: " + text); } } } @@ -629,30 +627,30 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - Logger.i("Network", `Disconnected from network: '${disconnectProcess.ssid}'`) + Logger.i("Network", `Disconnected from network: '${disconnectProcess.ssid}'`); ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.disconnected", { "ssid": disconnectProcess.ssid - }), "wifi-off") + }), "wifi-off"); // Immediately update UI on successful disconnect - root.updateNetworkStatus(disconnectProcess.ssid, false) - root.disconnectingFrom = "" + root.updateNetworkStatus(disconnectProcess.ssid, false); + root.disconnectingFrom = ""; // Do a scan to refresh the list - delayedScanTimer.interval = 1000 - delayedScanTimer.restart() + delayedScanTimer.interval = 1000; + delayedScanTimer.restart(); } } stderr: StdioCollector { onStreamFinished: { - root.disconnectingFrom = "" + root.disconnectingFrom = ""; if (text.trim()) { - Logger.w("Network", "Disconnect error: " + text) + Logger.w("Network", "Disconnect error: " + text); } // Still trigger a scan even on error - delayedScanTimer.interval = 5000 - delayedScanTimer.restart() + delayedScanTimer.interval = 5000; + delayedScanTimer.restart(); } } } @@ -694,36 +692,36 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - Logger.i("Network", `Forget network: "${forgetProcess.ssid}"`) - Logger.d("Network", text.trim().replace(/[\r\n]/g, " ")) + Logger.i("Network", `Forget network: "${forgetProcess.ssid}"`); + Logger.d("Network", text.trim().replace(/[\r\n]/g, " ")); // Update both cached and existing status immediately - let nets = root.networks + let nets = root.networks; if (nets[forgetProcess.ssid]) { - nets[forgetProcess.ssid].cached = false - nets[forgetProcess.ssid].existing = false + nets[forgetProcess.ssid].cached = false; + nets[forgetProcess.ssid].existing = false; // Trigger property change - root.networks = ({}) - root.networks = nets + root.networks = ({}); + root.networks = nets; } - root.forgettingNetwork = "" + root.forgettingNetwork = ""; // Scan to verify the profile is gone - delayedScanTimer.interval = 5000 - delayedScanTimer.restart() + delayedScanTimer.interval = 5000; + delayedScanTimer.restart(); } } stderr: StdioCollector { onStreamFinished: { - root.forgettingNetwork = "" + root.forgettingNetwork = ""; if (text.trim() && !text.includes("No profiles found")) { - Logger.w("Network", "Forget error: " + text) + Logger.w("Network", "Forget error: " + text); } // Still Trigger a scan even on error - delayedScanTimer.interval = 5000 - delayedScanTimer.restart() + delayedScanTimer.interval = 5000; + delayedScanTimer.restart(); } } } diff --git a/Services/Noctalia/GitHubService.qml b/Services/Noctalia/GitHubService.qml index 6f7c1bf4..dff19b2f 100644 --- a/Services/Noctalia/GitHubService.qml +++ b/Services/Noctalia/GitHubService.qml @@ -25,17 +25,17 @@ Singleton { onFileChanged: reload() onAdapterUpdated: writeAdapter() Component.onCompleted: { - reload() + reload(); } onLoaded: { - loadFromCache() + loadFromCache(); } onLoadFailed: function (error) { if (error.toString().includes("No such file") || error === 2) { // Fetch data after a short delay to ensure file is created Qt.callLater(() => { - fetchFromGitHub() - }) + fetchFromGitHub(); + }); } } @@ -50,58 +50,58 @@ Singleton { // -------------------------------- function loadFromCache() { - const now = Time.timestamp + const now = Time.timestamp; if (!data.timestamp || (now >= data.timestamp + githubUpdateFrequency)) { - Logger.d("GitHub", "Cache expired or missing, fetching new data") - fetchFromGitHub() - return + Logger.d("GitHub", "Cache expired or missing, fetching new data"); + fetchFromGitHub(); + return; } - Logger.d("GitHub", "Loading cached GitHub data (age:", Math.round((now - data.timestamp) / 60), "minutes)") + Logger.d("GitHub", "Loading cached GitHub data (age:", Math.round((now - data.timestamp) / 60), "minutes)"); if (data.version) { - root.latestVersion = data.version + root.latestVersion = data.version; } if (data.contributors) { - root.contributors = data.contributors + root.contributors = data.contributors; } } // -------------------------------- function fetchFromGitHub() { if (isFetchingData) { - Logger.w("GitHub", "GitHub data is still fetching") - return + Logger.w("GitHub", "GitHub data is still fetching"); + return; } - isFetchingData = true - versionProcess.running = true - contributorsProcess.running = true + isFetchingData = true; + versionProcess.running = true; + contributorsProcess.running = true; } // -------------------------------- function saveData() { - data.timestamp = Time.timestamp - Logger.d("GitHub", "Saving data to cache file:", githubDataFile) - Logger.d("GitHub", "Data to save - version:", data.version, "contributors:", data.contributors.length) + data.timestamp = Time.timestamp; + Logger.d("GitHub", "Saving data to cache file:", githubDataFile); + Logger.d("GitHub", "Data to save - version:", data.version, "contributors:", data.contributors.length); // Ensure cache directory exists - Quickshell.execDetached(["mkdir", "-p", Settings.cacheDir]) + Quickshell.execDetached(["mkdir", "-p", Settings.cacheDir]); Qt.callLater(() => { // Use direct ID reference to the FileView - githubDataFileView.writeAdapter() - Logger.d("GitHub", "Cache file written successfully") - }) + githubDataFileView.writeAdapter(); + Logger.d("GitHub", "Cache file written successfully"); + }); } // -------------------------------- function resetCache() { - data.version = I18n.tr("system.unknown-version") - data.contributors = [] - data.timestamp = 0 + data.version = I18n.tr("system.unknown-version"); + data.contributors = []; + data.timestamp = 0; // Try to fetch immediately - fetchFromGitHub() + fetchFromGitHub(); } Process { @@ -112,26 +112,26 @@ Singleton { stdout: StdioCollector { onStreamFinished: { try { - const response = text + const response = text; if (response && response.trim()) { - const data = JSON.parse(response) + const data = JSON.parse(response); if (data.tag_name) { - const version = data.tag_name - root.data.version = version - root.latestVersion = version - Logger.d("GitHub", "Latest version fetched from GitHub:", version) + const version = data.tag_name; + root.data.version = version; + root.latestVersion = version; + Logger.d("GitHub", "Latest version fetched from GitHub:", version); } else { - Logger.w("GitHub", "No tag_name in GitHub response") + Logger.w("GitHub", "No tag_name in GitHub response"); } } else { - Logger.w("GitHub", "Empty response from GitHub API") + Logger.w("GitHub", "Empty response from GitHub API"); } } catch (e) { - Logger.e("GitHub", "Failed to parse version:", e) + Logger.e("GitHub", "Failed to parse version:", e); } // Check if both processes are done - checkAndSaveData() + checkAndSaveData(); } } } @@ -144,27 +144,27 @@ Singleton { stdout: StdioCollector { onStreamFinished: { try { - const response = text - Logger.d("GitHub", "Raw contributors response length:", response ? response.length : 0) + const response = text; + Logger.d("GitHub", "Raw contributors response length:", response ? response.length : 0); if (response && response.trim()) { - const data = JSON.parse(response) - Logger.d("GitHub", "Parsed contributors data type:", typeof data, "length:", Array.isArray(data) ? data.length : "not array") - root.data.contributors = data || [] - root.contributors = root.data.contributors - Logger.d("GitHub", "Contributors fetched from GitHub:", root.contributors.length) + const data = JSON.parse(response); + Logger.d("GitHub", "Parsed contributors data type:", typeof data, "length:", Array.isArray(data) ? data.length : "not array"); + root.data.contributors = data || []; + root.contributors = root.data.contributors; + Logger.d("GitHub", "Contributors fetched from GitHub:", root.contributors.length); } else { - Logger.w("GitHub", "Empty response from GitHub API for contributors") - root.data.contributors = [] - root.contributors = [] + Logger.w("GitHub", "Empty response from GitHub API for contributors"); + root.data.contributors = []; + root.contributors = []; } } catch (e) { - Logger.e("GitHub", "Failed to parse contributors:", e) - root.data.contributors = [] - root.contributors = [] + Logger.e("GitHub", "Failed to parse contributors:", e); + root.data.contributors = []; + root.contributors = []; } // Check if both processes are done - checkAndSaveData() + checkAndSaveData(); } } } @@ -173,8 +173,8 @@ Singleton { function checkAndSaveData() { // Only save when both processes are finished if (!versionProcess.running && !contributorsProcess.running) { - root.isFetchingData = false - root.saveData() + root.isFetchingData = false; + root.saveData(); } } } diff --git a/Services/Noctalia/UpdateService.qml b/Services/Noctalia/UpdateService.qml index d350a71e..15b1b676 100644 --- a/Services/Noctalia/UpdateService.qml +++ b/Services/Noctalia/UpdateService.qml @@ -15,16 +15,16 @@ Singleton { // Internal helpers function getVersion() { - return root.currentVersion + return root.currentVersion; } function checkForUpdates() { // TODO: Implement update checking logic - Logger.i("UpdateService", "Checking for updates...") + Logger.i("UpdateService", "Checking for updates..."); } function init() { // Ensure the singleton is created - Logger.i("UpdateService", "Version:", root.currentVersion) + Logger.i("UpdateService", "Version:", root.currentVersion); } } diff --git a/Services/Power/IdleInhibitorService.qml b/Services/Power/IdleInhibitorService.qml index 1148134d..d9338684 100644 --- a/Services/Power/IdleInhibitorService.qml +++ b/Services/Power/IdleInhibitorService.qml @@ -18,8 +18,8 @@ Singleton { property string strategy: "systemd" // "systemd", "wayland", or "auto" function init() { - Logger.i("IdleInhibitor", "Service started") - detectStrategy() + Logger.i("IdleInhibitor", "Service started"); + detectStrategy(); } // Auto-detect the best strategy @@ -27,113 +27,112 @@ Singleton { if (strategy === "auto") { // Check if systemd-inhibit is available try { - var systemdResult = Quickshell.execDetached(["which", "systemd-inhibit"]) - strategy = "systemd" - Logger.d("IdleInhibitor", "Using systemd-inhibit strategy") - return - } catch (e) { + var systemdResult = Quickshell.execDetached(["which", "systemd-inhibit"]); + strategy = "systemd"; + Logger.d("IdleInhibitor", "Using systemd-inhibit strategy"); + return; + } catch (e) // systemd-inhibit not found, try Wayland tools - } + {} try { - var waylandResult = Quickshell.execDetached(["which", "wayhibitor"]) - strategy = "wayland" - Logger.d("IdleInhibitor", "Using wayhibitor strategy") - return - } catch (e) { + var waylandResult = Quickshell.execDetached(["which", "wayhibitor"]); + strategy = "wayland"; + Logger.d("IdleInhibitor", "Using wayhibitor strategy"); + return; + } catch (e) // wayhibitor not found - } + {} - Logger.w("IdleInhibitor", "No suitable inhibitor found - will try systemd as fallback") - strategy = "systemd" // Fallback to systemd even if not detected + Logger.w("IdleInhibitor", "No suitable inhibitor found - will try systemd as fallback"); + strategy = "systemd"; // Fallback to systemd even if not detected } } // Add an inhibitor function addInhibitor(id, reason = "Application request") { if (activeInhibitors.includes(id)) { - Logger.w("IdleInhibitor", "Inhibitor already active:", id) - return false + Logger.w("IdleInhibitor", "Inhibitor already active:", id); + return false; } - activeInhibitors.push(id) - updateInhibition(reason) - Logger.d("IdleInhibitor", "Added inhibitor:", id) - return true + activeInhibitors.push(id); + updateInhibition(reason); + Logger.d("IdleInhibitor", "Added inhibitor:", id); + return true; } // Remove an inhibitor function removeInhibitor(id) { - const index = activeInhibitors.indexOf(id) + const index = activeInhibitors.indexOf(id); if (index === -1) { - Logger.w("IdleInhibitor", "Inhibitor not found:", id) - return false + Logger.w("IdleInhibitor", "Inhibitor not found:", id); + return false; } - activeInhibitors.splice(index, 1) - updateInhibition() - Logger.d("IdleInhibitor", "Removed inhibitor:", id) - return true + activeInhibitors.splice(index, 1); + updateInhibition(); + Logger.d("IdleInhibitor", "Removed inhibitor:", id); + return true; } // Update the actual system inhibition function updateInhibition(newReason = reason) { - const shouldInhibit = activeInhibitors.length > 0 + const shouldInhibit = activeInhibitors.length > 0; if (shouldInhibit === isInhibited) { - return + return; // No change needed } if (shouldInhibit) { - startInhibition(newReason) + startInhibition(newReason); } else { - stopInhibition() + stopInhibition(); } } // Start system inhibition function startInhibition(newReason) { - reason = newReason + reason = newReason; if (strategy === "systemd") { - startSystemdInhibition() + startSystemdInhibition(); } else if (strategy === "wayland") { - startWaylandInhibition() + startWaylandInhibition(); } else { - Logger.w("IdleInhibitor", "No inhibition strategy available") - return + Logger.w("IdleInhibitor", "No inhibition strategy available"); + return; } - isInhibited = true - Logger.i("IdleInhibitor", "Started inhibition:", reason) + isInhibited = true; + Logger.i("IdleInhibitor", "Started inhibition:", reason); } // Stop system inhibition function stopInhibition() { if (!isInhibited) - return - + return; if (inhibitorProcess.running) { - inhibitorProcess.signal(15) // SIGTERM + inhibitorProcess.signal(15); // SIGTERM } - isInhibited = false - Logger.i("IdleInhibitor", "Stopped inhibition") + isInhibited = false; + Logger.i("IdleInhibitor", "Stopped inhibition"); } // Systemd inhibition using systemd-inhibit function startSystemdInhibition() { - inhibitorProcess.command = ["systemd-inhibit", "--what=idle", "--why=" + reason, "--mode=block", "sleep", "infinity"] - inhibitorProcess.running = true + inhibitorProcess.command = ["systemd-inhibit", "--what=idle", "--why=" + reason, "--mode=block", "sleep", "infinity"]; + inhibitorProcess.running = true; } // Wayland inhibition using wayhibitor or similar function startWaylandInhibition() { - inhibitorProcess.command = ["wayhibitor"] - inhibitorProcess.running = true + inhibitorProcess.command = ["wayhibitor"]; + inhibitorProcess.running = true; } // Process for maintaining the inhibition @@ -143,13 +142,13 @@ Singleton { onExited: function (exitCode, exitStatus) { if (isInhibited) { - Logger.w("IdleInhibitor", "Inhibitor process exited unexpectedly:", exitCode) - isInhibited = false + Logger.w("IdleInhibitor", "Inhibitor process exited unexpectedly:", exitCode); + isInhibited = false; } } onStarted: function () { - Logger.d("IdleInhibitor", "Inhibitor process started successfully") + Logger.d("IdleInhibitor", "Inhibitor process started successfully"); } } @@ -159,14 +158,14 @@ Singleton { interval: 1000 // 1 second onTriggered: function () { if (timeout == null) { - inhibitorTimeout.stop() - return + inhibitorTimeout.stop(); + return; } - timeout -= 1 + timeout -= 1; if (timeout <= 0) { - removeManualInhibitor() - return + removeManualInhibitor(); + return; } } } @@ -174,84 +173,84 @@ Singleton { // Manual toggle for user control function manualToggle() { // clear any existing timeout - timeout = null + timeout = null; if (activeInhibitors.includes("manual")) { - removeManualInhibitor() - return false + removeManualInhibitor(); + return false; } else { - addManualInhibitor(null) - return true + addManualInhibitor(null); + return true; } } function changeTimeout(delta) { if (timeout == null && delta < 0) { // no inhibitor, ignored - return + return; } if (timeout == null && delta > 0) { // enable manual inhibitor and set timeout - addManualInhibitor(timeout + delta) - return + addManualInhibitor(timeout + delta); + return; } if (timeout + delta <= 0) { // disable manual inhibitor - removeManualInhibitor() - return + removeManualInhibitor(); + return; } if (timeout + delta > 0) { // change timeout - addManualInhibitor(timeout + delta) - return + addManualInhibitor(timeout + delta); + return; } } function removeManualInhibitor() { if (timeout !== null) { - timeout = null + timeout = null; if (inhibitorTimeout.running) { - inhibitorTimeout.stop() + inhibitorTimeout.stop(); } } if (activeInhibitors.includes("manual")) { - removeInhibitor("manual") - ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.disabled"), "keep-awake-off") - Logger.i("IdleInhibitor", "Manual inhibition disabled") + removeInhibitor("manual"); + ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.disabled"), "keep-awake-off"); + Logger.i("IdleInhibitor", "Manual inhibition disabled"); } } function addManualInhibitor(timeoutSec) { if (!activeInhibitors.includes("manual")) { - addInhibitor("manual", "Manually activated by user") - ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.enabled"), "keep-awake-on") + addInhibitor("manual", "Manually activated by user"); + ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.enabled"), "keep-awake-on"); } if (timeoutSec === null && timeout === null) { - Logger.i("IdleInhibitor", "Manual inhibition enabled") - return + Logger.i("IdleInhibitor", "Manual inhibition enabled"); + return; } else if (timeoutSec !== null && timeout === null) { - timeout = timeoutSec - inhibitorTimeout.start() - Logger.i("IdleInhibitor", "Manual inhibition enabled with timeout:", timeoutSec) - return + timeout = timeoutSec; + inhibitorTimeout.start(); + Logger.i("IdleInhibitor", "Manual inhibition enabled with timeout:", timeoutSec); + return; } else if (timeoutSec !== null && timeout !== null) { - timeout = timeoutSec - Logger.i("IdleInhibitor", "Manual inhibition timeout changed to:", timeoutSec) - return + timeout = timeoutSec; + Logger.i("IdleInhibitor", "Manual inhibition timeout changed to:", timeoutSec); + return; } else if (timeoutSec === null && timeout !== null) { - timeout = null - inhibitorTimeout.stop() - Logger.i("IdleInhibitor", "Manual inhibition timeout cleared") - return + timeout = null; + inhibitorTimeout.stop(); + Logger.i("IdleInhibitor", "Manual inhibition timeout cleared"); + return; } } // Clean up on shutdown Component.onDestruction: { - stopInhibition() + stopInhibition(); } } diff --git a/Services/Power/PowerProfileService.qml b/Services/Power/PowerProfileService.qml index f086e9c1..68037318 100644 --- a/Services/Power/PowerProfileService.qml +++ b/Services/Power/PowerProfileService.qml @@ -18,82 +18,82 @@ Singleton { function getName(p) { if (!available) - return "Unknown" + return "Unknown"; - const prof = (p !== undefined) ? p : profile + const prof = (p !== undefined) ? p : profile; switch (prof) { case PowerProfile.Performance: - return "Performance" + return "Performance"; case PowerProfile.Balanced: - return "Balanced" + return "Balanced"; case PowerProfile.PowerSaver: - return "Power saver" + return "Power saver"; default: - return "Unknown" + return "Unknown"; } } function getIcon(p) { if (!available) - return "balanced" + return "balanced"; - const prof = (p !== undefined) ? p : profile + const prof = (p !== undefined) ? p : profile; switch (prof) { case PowerProfile.Performance: - return "performance" + return "performance"; case PowerProfile.Balanced: - return "balanced" + return "balanced"; case PowerProfile.PowerSaver: - return "powersaver" + return "powersaver"; default: - return "balanced" + return "balanced"; } } function init() { - Logger.d("PowerProfileService", "Service started") + Logger.d("PowerProfileService", "Service started"); } function setProfile(p) { if (!available) - return + return; try { - powerProfiles.profile = p + powerProfiles.profile = p; } catch (e) { - Logger.e("PowerProfileService", "Failed to set profile:", e) + Logger.e("PowerProfileService", "Failed to set profile:", e); } } function cycleProfile() { if (!available) - return - const current = powerProfiles.profile + return; + const current = powerProfiles.profile; if (current === PowerProfile.Performance) - setProfile(PowerProfile.PowerSaver) + setProfile(PowerProfile.PowerSaver); else if (current === PowerProfile.Balanced) - setProfile(PowerProfile.Performance) + setProfile(PowerProfile.Performance); else if (current === PowerProfile.PowerSaver) - setProfile(PowerProfile.Balanced) + setProfile(PowerProfile.Balanced); } function isDefault() { if (!available) - return true - return (profile === PowerProfile.Balanced) + return true; + return (profile === PowerProfile.Balanced); } Connections { target: powerProfiles function onProfileChanged() { - root.profile = powerProfiles.profile + root.profile = powerProfiles.profile; // Only show toast if we have a valid profile name (not "Unknown") - const profileName = root.getName() + const profileName = root.getName(); if (profileName !== "Unknown") { ToastService.showNotice(I18n.tr("toast.power-profile.changed"), I18n.tr("toast.power-profile.profile-name", { "profile": profileName - }), profileName.toLowerCase().replace(" ", "")) + }), profileName.toLowerCase().replace(" ", "")); } } } @@ -103,18 +103,18 @@ Singleton { // - Turning animation off // - Do Not Disturb function toggleNoctaliaPerformance() { - noctaliaPerformanceMode = !noctaliaPerformanceMode + noctaliaPerformanceMode = !noctaliaPerformanceMode; } function setNoctaliaPerformance(value) { - noctaliaPerformanceMode = value + noctaliaPerformanceMode = value; } onNoctaliaPerformanceModeChanged: { if (noctaliaPerformanceMode) { - ToastService.showNotice(I18n.tr("toast.noctalia-performance.label"), I18n.tr("toast.noctalia-performance.enabled"), "rocket") + ToastService.showNotice(I18n.tr("toast.noctalia-performance.label"), I18n.tr("toast.noctalia-performance.enabled"), "rocket"); } else { - ToastService.showNotice(I18n.tr("toast.noctalia-performance.label"), I18n.tr("toast.noctalia-performance.disabled"), "rocket-off") + ToastService.showNotice(I18n.tr("toast.noctalia-performance.label"), I18n.tr("toast.noctalia-performance.disabled"), "rocket-off"); } } } diff --git a/Services/System/FontService.qml b/Services/System/FontService.qml index 1ffeee77..f9be21b9 100644 --- a/Services/System/FontService.qml +++ b/Services/System/FontService.qml @@ -26,223 +26,222 @@ Singleton { // ------------------------------------------- function init() { - Logger.i("Font", "Service started") - loadFontconfigMonospaceFonts() + Logger.i("Font", "Service started"); + loadFontconfigMonospaceFonts(); } function loadFontconfigMonospaceFonts() { - fontconfigProcess.command = ["fc-list", ":mono", "family"] - fontconfigProcess.running = true + fontconfigProcess.command = ["fc-list", ":mono", "family"]; + fontconfigProcess.running = true; } function loadSystemFonts() { if (isLoading) - return + return; + Logger.d("Font", "Loading system fonts..."); + isLoading = true; - Logger.d("Font", "Loading system fonts...") - isLoading = true - - var fontFamilies = Qt.fontFamilies() + var fontFamilies = Qt.fontFamilies(); // Pre-sort fonts before processing to ensure consistent order fontFamilies.sort(function (a, b) { - return a.localeCompare(b) - }) + return a.localeCompare(b); + }); // Clear existing models - availableFonts.clear() - monospaceFonts.clear() - displayFonts.clear() - fontCache = {} + availableFonts.clear(); + monospaceFonts.clear(); + displayFonts.clear(); + fontCache = {}; // Process fonts in chunks to avoid blocking - processFontsAsync(fontFamilies, 0) + processFontsAsync(fontFamilies, 0); } function processFontsAsync(fontFamilies, startIndex) { - var endIndex = Math.min(startIndex + chunkSize, fontFamilies.length) - var hasMore = endIndex < fontFamilies.length + var endIndex = Math.min(startIndex + chunkSize, fontFamilies.length); + var hasMore = endIndex < fontFamilies.length; // Batch arrays to append all at once (much faster than individual appends) - var availableBatch = [] - var monospaceBatch = [] - var displayBatch = [] + var availableBatch = []; + var monospaceBatch = []; + var displayBatch = []; for (var i = startIndex; i < endIndex; i++) { - var fontName = fontFamilies[i] + var fontName = fontFamilies[i]; if (!fontName || fontName.trim() === "") - continue + continue; // Add to available fonts var fontObj = { "key": fontName, "name": fontName - } - availableBatch.push(fontObj) + }; + availableBatch.push(fontObj); // Check monospace (with caching) if (isMonospaceFont(fontName)) { - monospaceBatch.push(fontObj) + monospaceBatch.push(fontObj); } // Check display font (with caching) if (isDisplayFont(fontName)) { - displayBatch.push(fontObj) + displayBatch.push(fontObj); } } // Batch append to models - batchAppendToModel(availableFonts, availableBatch) - batchAppendToModel(monospaceFonts, monospaceBatch) - batchAppendToModel(displayFonts, displayBatch) + batchAppendToModel(availableFonts, availableBatch); + batchAppendToModel(monospaceFonts, monospaceBatch); + batchAppendToModel(displayFonts, displayBatch); if (hasMore) { // Continue processing in next frame Qt.callLater(function () { - processFontsAsync(fontFamilies, endIndex) - }) + processFontsAsync(fontFamilies, endIndex); + }); } else { // Finished loading all fonts - finalizeFontLoading() + finalizeFontLoading(); } } function batchAppendToModel(model, items) { for (var i = 0; i < items.length; i++) { - model.append(items[i]) + model.append(items[i]); } } function finalizeFontLoading() { // Add fallbacks if needed (models are already sorted) if (monospaceFonts.count === 0) { - addFallbackFonts(monospaceFonts, ["DejaVu Sans Mono"]) + addFallbackFonts(monospaceFonts, ["DejaVu Sans Mono"]); } if (displayFonts.count === 0) { - addFallbackFonts(displayFonts, ["Inter", "Roboto", "DejaVu Sans"]) + addFallbackFonts(displayFonts, ["Inter", "Roboto", "DejaVu Sans"]); } - fontsLoaded = true - isLoading = false - Logger.d("Font", "Loaded", availableFonts.count, "fonts:", monospaceFonts.count, "monospace,", displayFonts.count, "display") + fontsLoaded = true; + isLoading = false; + Logger.d("Font", "Loaded", availableFonts.count, "fonts:", monospaceFonts.count, "monospace,", displayFonts.count, "display"); } function isMonospaceFont(fontName) { // Check cache first if (fontCache.hasOwnProperty(fontName)) { - return fontCache[fontName].isMonospace + return fontCache[fontName].isMonospace; } - var result = false + var result = false; // O(1) lookup using object instead of indexOf if (fontconfigMonospaceFonts.hasOwnProperty(fontName)) { - result = true + result = true; } else { // Fallback: check for basic monospace patterns - var lowerFontName = fontName.toLowerCase() + var lowerFontName = fontName.toLowerCase(); if (lowerFontName.includes("mono") || lowerFontName.includes("monospace")) { - result = true + result = true; } } // Cache the result if (!fontCache[fontName]) { - fontCache[fontName] = {} + fontCache[fontName] = {}; } - fontCache[fontName].isMonospace = result + fontCache[fontName].isMonospace = result; - return result + return result; } function isDisplayFont(fontName) { // Check cache first if (fontCache.hasOwnProperty(fontName) && fontCache[fontName].hasOwnProperty('isDisplay')) { - return fontCache[fontName].isDisplay + return fontCache[fontName].isDisplay; } - var result = false - var lowerFontName = fontName.toLowerCase() + var result = false; + var lowerFontName = fontName.toLowerCase(); if (lowerFontName.includes("display") || lowerFontName.includes("headline") || lowerFontName.includes("title")) { - result = true + result = true; } // Essential fallback fonts only - var essentialFonts = ["Inter", "Roboto", "DejaVu Sans"] + var essentialFonts = ["Inter", "Roboto", "DejaVu Sans"]; if (essentialFonts.indexOf(fontName) !== -1) { - result = true + result = true; } // Cache the result if (!fontCache[fontName]) { - fontCache[fontName] = {} + fontCache[fontName] = {}; } - fontCache[fontName].isDisplay = result + fontCache[fontName].isDisplay = result; - return result + return result; } function sortModel(model) { // Convert to array - var fontsArray = [] + var fontsArray = []; for (var i = 0; i < model.count; i++) { fontsArray.push({ "key": model.get(i).key, "name": model.get(i).name - }) + }); } // Sort fontsArray.sort(function (a, b) { - return a.name.localeCompare(b.name) - }) + return a.name.localeCompare(b.name); + }); // Clear and rebuild - model.clear() - batchAppendToModel(model, fontsArray) + model.clear(); + batchAppendToModel(model, fontsArray); } function addFallbackFonts(model, fallbackFonts) { // Build a set of existing fonts for O(1) lookup - var existingFonts = {} + var existingFonts = {}; for (var i = 0; i < model.count; i++) { - existingFonts[model.get(i).name] = true + existingFonts[model.get(i).name] = true; } - var toAdd = [] + var toAdd = []; for (var j = 0; j < fallbackFonts.length; j++) { - var fontName = fallbackFonts[j] + var fontName = fallbackFonts[j]; if (!existingFonts[fontName]) { toAdd.push({ "key": fontName, "name": fontName - }) + }); } } if (toAdd.length > 0) { - batchAppendToModel(model, toAdd) - sortModel(model) + batchAppendToModel(model, toAdd); + sortModel(model); } } function searchFonts(query) { if (!query || query.trim() === "") - return availableFonts + return availableFonts; - var results = [] - var lowerQuery = query.toLowerCase() + var results = []; + var lowerQuery = query.toLowerCase(); for (var i = 0; i < availableFonts.count; i++) { - var font = availableFonts.get(i) + var font = availableFonts.get(i); if (font.name.toLowerCase().includes(lowerQuery)) { - results.push(font) + results.push(font); } } - return results + return results; } // Process for fontconfig commands @@ -253,28 +252,28 @@ Singleton { stdout: StdioCollector { onStreamFinished: { if (this.text !== "") { - var lines = this.text.split('\n') + var lines = this.text.split('\n'); // Use object for O(1) lookup instead of array - var monospaceLookup = {} + var monospaceLookup = {}; for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim() + var line = lines[i].trim(); if (line && line !== "") { - monospaceLookup[line] = true + monospaceLookup[line] = true; } } - fontconfigMonospaceFonts = monospaceLookup + fontconfigMonospaceFonts = monospaceLookup; } - loadSystemFonts() + loadSystemFonts(); } } onExited: function (exitCode, exitStatus) { if (exitCode !== 0) { - fontconfigMonospaceFonts = {} + fontconfigMonospaceFonts = {}; } - loadSystemFonts() + loadSystemFonts(); } } } diff --git a/Services/System/HostService.qml b/Services/System/HostService.qml index 92e8fc7f..84946055 100644 --- a/Services/System/HostService.qml +++ b/Services/System/HostService.qml @@ -22,76 +22,75 @@ Singleton { readonly property string displayName: { // Explicit override if (envRealName && envRealName.length > 0) { - return envRealName + return envRealName; } // Name from getent if (realName && realName.length > 0) { - return realName + return realName; } // Fallback: capitalized $USER if (username && username.length > 0) { - return username.charAt(0).toUpperCase() + username.slice(1) + return username.charAt(0).toUpperCase() + username.slice(1); } // Last resort: placeholder - return "User" + return "User"; } function init() { - Logger.i("HostService", "Service started") + Logger.i("HostService", "Service started"); } // Internal helpers function buildCandidates(name) { - const n = (name || "").trim() + const n = (name || "").trim(); if (!n) - return [] + return []; - const sizes = ["512x512", "256x256", "128x128", "64x64", "48x48", "32x32", "24x24", "22x22", "16x16"] - const exts = ["svg", "png"] - const candidates = [] + const sizes = ["512x512", "256x256", "128x128", "64x64", "48x48", "32x32", "24x24", "22x22", "16x16"]; + const exts = ["svg", "png"]; + const candidates = []; // pixmaps for (const ext of exts) { - candidates.push(`/usr/share/pixmaps/${n}.${ext}`) + candidates.push(`/usr/share/pixmaps/${n}.${ext}`); } // hicolor scalable and raster sizes - candidates.push(`/usr/share/icons/hicolor/scalable/apps/${n}.svg`) + candidates.push(`/usr/share/icons/hicolor/scalable/apps/${n}.svg`); for (const s of sizes) { for (const ext of exts) { - candidates.push(`/usr/share/icons/hicolor/${s}/apps/${n}.${ext}`) + candidates.push(`/usr/share/icons/hicolor/${s}/apps/${n}.${ext}`); } } // NixOS hicolor paths - candidates.push(`/run/current-system/sw/share/icons/hicolor/scalable/apps/${n}.svg`) + candidates.push(`/run/current-system/sw/share/icons/hicolor/scalable/apps/${n}.svg`); for (const s of sizes) { for (const ext of exts) { - candidates.push(`/run/current-system/sw/share/icons/hicolor/${s}/apps/${n}.${ext}`) + candidates.push(`/run/current-system/sw/share/icons/hicolor/${s}/apps/${n}.${ext}`); } } // Generic icon themes under /usr/share/icons (common cases) for (const ext of exts) { - candidates.push(`/usr/share/icons/${n}.${ext}`) - candidates.push(`/usr/share/icons/${n}/${n}.${ext}`) - candidates.push(`/usr/share/icons/${n}/apps/${n}.${ext}`) + candidates.push(`/usr/share/icons/${n}.${ext}`); + candidates.push(`/usr/share/icons/${n}/${n}.${ext}`); + candidates.push(`/usr/share/icons/${n}/apps/${n}.${ext}`); } - return candidates + return candidates; } function resolveLogo(name) { - const all = buildCandidates(name) + const all = buildCandidates(name); if (all.length === 0) - return - - const script = all.map(p => `if [ -f "${p}" ]; then echo "${p}"; exit 0; fi`).join("; ") + "; exit 1" - probe.command = ["sh", "-c", script] - probe.running = true + return; + const script = all.map(p => `if [ -f "${p}" ]; then echo "${p}"; exit 0; fi`).join("; ") + "; exit 1"; + probe.command = ["sh", "-c", script]; + probe.running = true; } // Read /etc/os-release and trigger resolution @@ -100,23 +99,23 @@ Singleton { path: "/etc/os-release" onLoaded: { try { - const lines = text().split("\n") + const lines = text().split("\n"); const val = k => { - const l = lines.find(x => x.startsWith(k + "=")) - return l ? l.split("=")[1].replace(/"/g, "") : "" - } - root.osPretty = val("PRETTY_NAME") || val("NAME") - Logger.i("HostService", root.osPretty) + const l = lines.find(x => x.startsWith(k + "=")); + return l ? l.split("=")[1].replace(/"/g, "") : ""; + }; + root.osPretty = val("PRETTY_NAME") || val("NAME"); + Logger.i("HostService", root.osPretty); - const osId = (val("ID") || "").toLowerCase() - root.isNixOS = osId === "nixos" || (root.osPretty || "").toLowerCase().includes("nixos") - const logoName = val("LOGO") + const osId = (val("ID") || "").toLowerCase(); + root.isNixOS = osId === "nixos" || (root.osPretty || "").toLowerCase().includes("nixos"); + const logoName = val("LOGO"); if (logoName) { - resolveLogo(logoName) + resolveLogo(logoName); } - root.isReady = true + root.isReady = true; } catch (e) { - Logger.w("HostService", "failed to read os-release", e) + Logger.w("HostService", "failed to read os-release", e); } } } @@ -124,13 +123,13 @@ Singleton { Process { id: probe onExited: code => { - const p = String(stdout.text || "").trim() + const p = String(stdout.text || "").trim(); if (code === 0 && p) { - root.osLogo = `file://${p}` - Logger.i("HostService", "found", root.osLogo) + root.osLogo = `file://${p}`; + Logger.i("HostService", "found", root.osLogo); } else { - root.osLogo = "" - Logger.w("HostService", "none found") + root.osLogo = ""; + Logger.w("HostService", "none found"); } } stdout: StdioCollector {} @@ -145,10 +144,10 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const name = String(text || "").trim() + const name = String(text || "").trim(); if (name.length > 0) { - root.realName = name - Logger.i("HostService", "resolved real name", name) + root.realName = name; + Logger.i("HostService", "resolved real name", name); } } } diff --git a/Services/System/NotificationService.qml b/Services/System/NotificationService.qml index 277938a1..59ff6ad3 100644 --- a/Services/System/NotificationService.qml +++ b/Services/System/NotificationService.qml @@ -5,10 +5,10 @@ import QtQuick.Window import Quickshell import Quickshell.Io import Quickshell.Services.Notifications +import "../../Helpers/sha256.js" as Checksum import qs.Commons import qs.Services.Power import qs.Services.UI -import "../../Helpers/sha256.js" as Checksum Singleton { id: root @@ -50,28 +50,30 @@ Singleton { antialiasing: true onStatusChanged: { - if (imageQueue.length === 0) - return - const req = imageQueue[0] + if (imageQueue.length === 0) { + return; + } + + const req = imageQueue[0]; if (status === Image.Ready) { - Quickshell.execDetached(["mkdir", "-p", Settings.cacheDirImagesNotifications]) + Quickshell.execDetached(["mkdir", "-p", Settings.cacheDirImagesNotifications]); grabToImage(result => { if (result.saveToFile(req.dest)) - updateImagePath(req.imageId, req.dest) - processNextImage() - }) + updateImagePath(req.imageId, req.dest); + processNextImage(); + }); } else if (status === Image.Error) { - processNextImage() + processNextImage(); } } function processNextImage() { - imageQueue.shift() + imageQueue.shift(); if (imageQueue.length > 0) { - source = imageQueue[0].src + source = imageQueue[0].src; } else { - source = "" + source = ""; } } } @@ -98,53 +100,53 @@ Singleton { target: targetNotification function onSummaryChanged() { - updateNotificationFromObject(targetDataId) + updateNotificationFromObject(targetDataId); } function onBodyChanged() { - updateNotificationFromObject(targetDataId) + updateNotificationFromObject(targetDataId); } function onAppNameChanged() { - updateNotificationFromObject(targetDataId) + updateNotificationFromObject(targetDataId); } function onUrgencyChanged() { - updateNotificationFromObject(targetDataId) + updateNotificationFromObject(targetDataId); } function onAppIconChanged() { - updateNotificationFromObject(targetDataId) + updateNotificationFromObject(targetDataId); } function onImageChanged() { - updateNotificationFromObject(targetDataId) + updateNotificationFromObject(targetDataId); } function onActionsChanged() { - updateNotificationFromObject(targetDataId) + updateNotificationFromObject(targetDataId); } } } function updateNotificationServer() { if (notificationServerLoader) { - notificationServerLoader.destroy() - notificationServerLoader = null + notificationServerLoader.destroy(); + notificationServerLoader = null; } if (Settings.isLoaded && Settings.data.notifications.enabled !== false) { - notificationServerLoader = notificationServerComponent.createObject(root) + notificationServerLoader = notificationServerComponent.createObject(root); } } Component.onCompleted: { if (Settings.isLoaded) { - updateNotificationServer() + updateNotificationServer(); } } Connections { target: Settings function onSettingsLoaded() { - updateNotificationServer() + updateNotificationServer(); } function onSettingsSaved() { - updateNotificationServer() + updateNotificationServer(); } } @@ -154,76 +156,75 @@ Singleton { "summary": summary || "", "body": body || "", "app": appName || "" - })) + })); } // Main handler function handleNotification(notification) { - const quickshellId = notification.id - const data = createData(notification) - addToHistory(data) + const quickshellId = notification.id; + const data = createData(notification); + addToHistory(data); if (root.doNotDisturb || PowerProfileService.noctaliaPerformanceMode) - return + return; // Check if this is a replacement notification - const existingInternalId = quickshellIdToInternalId[quickshellId] + const existingInternalId = quickshellIdToInternalId[quickshellId]; if (existingInternalId && activeNotifications[existingInternalId]) { - updateExistingNotification(existingInternalId, notification, data) - return + updateExistingNotification(existingInternalId, notification, data); + return; } // Check for duplicate content - const duplicateId = findDuplicateNotification(data) + const duplicateId = findDuplicateNotification(data); if (duplicateId) { - removeNotification(duplicateId) + removeNotification(duplicateId); } // Add new notification - addNewNotification(quickshellId, notification, data) + addNewNotification(quickshellId, notification, data); } function updateExistingNotification(internalId, notification, data) { - const index = findNotificationIndex(internalId) + const index = findNotificationIndex(internalId); if (index < 0) - return - - const existing = activeList.get(index) - const oldTimestamp = existing.timestamp - const oldProgress = existing.progress + return; + const existing = activeList.get(index); + const oldTimestamp = existing.timestamp; + const oldProgress = existing.progress; // Update properties (keeping original timestamp and progress) - activeList.setProperty(index, "summary", data.summary) - activeList.setProperty(index, "body", data.body) - activeList.setProperty(index, "appName", data.appName) - activeList.setProperty(index, "urgency", data.urgency) - activeList.setProperty(index, "expireTimeout", data.expireTimeout) - activeList.setProperty(index, "originalImage", data.originalImage) - activeList.setProperty(index, "cachedImage", data.cachedImage) - activeList.setProperty(index, "actionsJson", data.actionsJson) - activeList.setProperty(index, "timestamp", oldTimestamp) - activeList.setProperty(index, "progress", oldProgress) + activeList.setProperty(index, "summary", data.summary); + activeList.setProperty(index, "body", data.body); + activeList.setProperty(index, "appName", data.appName); + activeList.setProperty(index, "urgency", data.urgency); + activeList.setProperty(index, "expireTimeout", data.expireTimeout); + activeList.setProperty(index, "originalImage", data.originalImage); + activeList.setProperty(index, "cachedImage", data.cachedImage); + activeList.setProperty(index, "actionsJson", data.actionsJson); + activeList.setProperty(index, "timestamp", oldTimestamp); + activeList.setProperty(index, "progress", oldProgress); // Update stored notification object - const notifData = activeNotifications[internalId] - notifData.notification = notification - notification.tracked = true - notification.closed.connect(() => removeNotification(internalId)) + const notifData = activeNotifications[internalId]; + notifData.notification = notification; + notification.tracked = true; + notification.closed.connect(() => removeNotification(internalId)); // Update metadata - notifData.metadata.urgency = data.urgency - notifData.metadata.duration = calculateDuration(data) + notifData.metadata.urgency = data.urgency; + notifData.metadata.duration = calculateDuration(data); } function addNewNotification(quickshellId, notification, data) { // Map IDs - quickshellIdToInternalId[quickshellId] = data.id + quickshellIdToInternalId[quickshellId] = data.id; // Create watcher const watcher = notificationWatcherComponent.createObject(root, { "targetNotification": notification, "targetDataId": data.id - }) + }); // Store notification data activeNotifications[data.id] = { @@ -236,61 +237,61 @@ Singleton { "paused": false, "pauseTime": 0 } - } + }; - notification.tracked = true - notification.closed.connect(() => removeNotification(data.id)) + notification.tracked = true; + notification.closed.connect(() => removeNotification(data.id)); // Add to list - activeList.insert(0, data) + activeList.insert(0, data); // Remove overflow while (activeList.count > maxVisible) { - const last = activeList.get(activeList.count - 1) - activeNotifications[last.id]?.notification?.dismiss() - activeList.remove(activeList.count - 1) - cleanupNotification(last.id) + const last = activeList.get(activeList.count - 1); + activeNotifications[last.id]?.notification?.dismiss(); + activeList.remove(activeList.count - 1); + cleanupNotification(last.id); } } function findDuplicateNotification(data) { - const contentId = getContentId(data.summary, data.body, data.appName) + const contentId = getContentId(data.summary, data.body, data.appName); for (var i = 0; i < activeList.count; i++) { - const existing = activeList.get(i) - const existingContentId = getContentId(existing.summary, existing.body, existing.appName) + const existing = activeList.get(i); + const existingContentId = getContentId(existing.summary, existing.body, existing.appName); if (existingContentId === contentId) { - return existing.id + return existing.id; } } - return null + return null; } function calculateDuration(data) { - const durations = [Settings.data.notifications?.lowUrgencyDuration * 1000 || 3000, Settings.data.notifications?.normalUrgencyDuration * 1000 || 8000, Settings.data.notifications?.criticalUrgencyDuration * 1000 || 15000] + const durations = [Settings.data.notifications?.lowUrgencyDuration * 1000 || 3000, Settings.data.notifications?.normalUrgencyDuration * 1000 || 8000, Settings.data.notifications?.criticalUrgencyDuration * 1000 || 15000]; if (Settings.data.notifications?.respectExpireTimeout) { if (data.expireTimeout === 0) - return -1 // Never expire + return -1; // Never expire if (data.expireTimeout > 0) - return data.expireTimeout + return data.expireTimeout; } - return durations[data.urgency] + return durations[data.urgency]; } function createData(n) { - const time = new Date() + const time = new Date(); const id = Checksum.sha256(JSON.stringify({ "summary": n.summary, "body": n.body, "app": n.appName, "time": time.getTime() - })) + })); - const image = n.image || getIcon(n.appIcon) - const imageId = generateImageId(n, image) - queueImage(image, imageId) + const image = n.image || getIcon(n.appIcon); + const imageId = generateImageId(n, image); + queueImage(image, imageId); return { "id": id, @@ -307,65 +308,63 @@ Singleton { "text": a.text || "Action", "identifier": a.identifier || "" }))) - } + }; } function findNotificationIndex(internalId) { for (var i = 0; i < activeList.count; i++) { if (activeList.get(i).id === internalId) { - return i + return i; } } - return -1 + return -1; } function updateNotificationFromObject(internalId) { - const notifData = activeNotifications[internalId] + const notifData = activeNotifications[internalId]; if (!notifData) - return - - const index = findNotificationIndex(internalId) + return; + const index = findNotificationIndex(internalId); if (index < 0) - return - - const data = createData(notifData.notification) - const existing = activeList.get(index) + return; + const data = createData(notifData.notification); + const existing = activeList.get(index); // Update properties (keeping timestamp and progress) - activeList.setProperty(index, "summary", data.summary) - activeList.setProperty(index, "body", data.body) - activeList.setProperty(index, "appName", data.appName) - activeList.setProperty(index, "urgency", data.urgency) - activeList.setProperty(index, "expireTimeout", data.expireTimeout) - activeList.setProperty(index, "originalImage", data.originalImage) - activeList.setProperty(index, "cachedImage", data.cachedImage) - activeList.setProperty(index, "actionsJson", data.actionsJson) + activeList.setProperty(index, "summary", data.summary); + activeList.setProperty(index, "body", data.body); + activeList.setProperty(index, "appName", data.appName); + activeList.setProperty(index, "urgency", data.urgency); + activeList.setProperty(index, "expireTimeout", data.expireTimeout); + activeList.setProperty(index, "originalImage", data.originalImage); + activeList.setProperty(index, "cachedImage", data.cachedImage); + activeList.setProperty(index, "actionsJson", data.actionsJson); // Update metadata - notifData.metadata.urgency = data.urgency - notifData.metadata.duration = calculateDuration(data) + notifData.metadata.urgency = data.urgency; + notifData.metadata.duration = calculateDuration(data); } function removeNotification(id) { - const index = findNotificationIndex(id) + const index = findNotificationIndex(id); if (index >= 0) { - activeList.remove(index) + activeList.remove(index); } - cleanupNotification(id) + cleanupNotification(id); } function cleanupNotification(id) { - const notifData = activeNotifications[id] + const notifData = activeNotifications[id]; if (notifData) { - notifData.watcher?.destroy() - delete activeNotifications[id] + notifData.watcher?.destroy(); + delete activeNotifications[id]; } // Clean up quickshell ID mapping for (const qsId in quickshellIdToInternalId) { if (quickshellIdToInternalId[qsId] === id) { - delete quickshellIdToInternalId[qsId] - break + delete quickshellIdToInternalId[qsId]; + break; } } } @@ -379,83 +378,80 @@ Singleton { } function updateAllProgress() { - const now = Date.now() - const toRemove = [] + const now = Date.now(); + const toRemove = []; for (var i = 0; i < activeList.count; i++) { - const notif = activeList.get(i) - const notifData = activeNotifications[notif.id] + const notif = activeList.get(i); + const notifData = activeNotifications[notif.id]; if (!notifData) - continue - - const meta = notifData.metadata + continue; + const meta = notifData.metadata; if (meta.duration === -1 || meta.paused) - continue - - const elapsed = now - meta.timestamp - const progress = Math.max(1.0 - (elapsed / meta.duration), 0.0) + continue; + const elapsed = now - meta.timestamp; + const progress = Math.max(1.0 - (elapsed / meta.duration), 0.0); if (progress <= 0) { - toRemove.push(notif.id) + toRemove.push(notif.id); } else if (Math.abs(notif.progress - progress) > 0.005) { - activeList.setProperty(i, "progress", progress) + activeList.setProperty(i, "progress", progress); } } if (toRemove.length > 0) { - animateAndRemove(toRemove[0]) + animateAndRemove(toRemove[0]); } } // Image handling function queueImage(path, imageId) { if (!path || !path.startsWith("image://") || !imageId) - return - - const dest = Settings.cacheDirImagesNotifications + imageId + ".png" + return; + const dest = Settings.cacheDirImagesNotifications + imageId + ".png"; for (const req of imageQueue) { if (req.imageId === imageId) - return + return; } imageQueue.push({ "src": path, "dest": dest, "imageId": imageId - }) + }); if (imageQueue.length === 1) - cacher.source = path + cacher.source = path; } function updateImagePath(id, path) { - updateModel(activeList, id, "cachedImage", path) - updateModel(historyList, id, "cachedImage", path) - saveHistory() + updateModel(activeList, id, "cachedImage", path); + updateModel(historyList, id, "cachedImage", path); + saveHistory(); } function updateModel(model, id, prop, value) { for (var i = 0; i < model.count; i++) { if (model.get(i).id === id) { - model.setProperty(i, prop, value) - break + model.setProperty(i, prop, value); + break; } } } // History management function addToHistory(data) { - historyList.insert(0, data) + historyList.insert(0, data); while (historyList.count > maxHistory) { - const old = historyList.get(historyList.count - 1) + const old = historyList.get(historyList.count - 1); if (old.cachedImage && !old.cachedImage.startsWith("image://")) { - Quickshell.execDetached(["rm", "-f", old.cachedImage]) + Quickshell.execDetached(["rm", "-f", old.cachedImage]); } - historyList.remove(historyList.count - 1) + historyList.remove(historyList.count - 1); } - saveHistory() + saveHistory(); } // Persistence - History @@ -466,7 +462,7 @@ Singleton { onLoaded: loadHistory() onLoadFailed: error => { if (error === 2) - writeAdapter() + writeAdapter(); } JsonAdapter { @@ -483,7 +479,7 @@ Singleton { onLoaded: loadState() onLoadFailed: error => { if (error === 2) - writeAdapter() + writeAdapter(); } JsonAdapter { @@ -499,36 +495,36 @@ Singleton { } function saveHistory() { - saveTimer.restart() + saveTimer.restart(); } function performSaveHistory() { try { - const items = [] + const items = []; for (var i = 0; i < historyList.count; i++) { - const n = historyList.get(i) - const copy = Object.assign({}, n) - copy.timestamp = n.timestamp.getTime() - items.push(copy) + const n = historyList.get(i); + const copy = Object.assign({}, n); + copy.timestamp = n.timestamp.getTime(); + items.push(copy); } - adapter.notifications = items - historyFileView.writeAdapter() + adapter.notifications = items; + historyFileView.writeAdapter(); } catch (e) { - Logger.e("Notifications", "Save history failed:", e) + Logger.e("Notifications", "Save history failed:", e); } } function loadHistory() { try { - historyList.clear() + historyList.clear(); for (const item of adapter.notifications || []) { - const time = new Date(item.timestamp) + const time = new Date(item.timestamp); - let cachedImage = item.cachedImage || "" + let cachedImage = item.cachedImage || ""; if (item.originalImage && item.originalImage.startsWith("image://") && !cachedImage) { - const imageId = generateImageId(item, item.originalImage) + const imageId = generateImageId(item, item.originalImage); if (imageId) { - cachedImage = Settings.cacheDirImagesNotifications + imageId + ".png" + cachedImage = Settings.cacheDirImagesNotifications + imageId + ".png"; } } @@ -541,196 +537,196 @@ Singleton { "timestamp": time, "originalImage": item.originalImage || "", "cachedImage": cachedImage - }) + }); } } catch (e) { - Logger.e("Notifications", "Load failed:", e) + Logger.e("Notifications", "Load failed:", e); } } function loadState() { try { - root.lastSeenTs = stateAdapter.lastSeenTs || 0 + root.lastSeenTs = stateAdapter.lastSeenTs || 0; if (root.lastSeenTs === 0 && Settings.data.notifications && Settings.data.notifications.lastSeenTs) { - root.lastSeenTs = Settings.data.notifications.lastSeenTs - saveState() - Logger.i("Notifications", "Migrated lastSeenTs from settings to state file") + root.lastSeenTs = Settings.data.notifications.lastSeenTs; + saveState(); + Logger.i("Notifications", "Migrated lastSeenTs from settings to state file"); } } catch (e) { - Logger.e("Notifications", "Load state failed:", e) + Logger.e("Notifications", "Load state failed:", e); } } function saveState() { try { - stateAdapter.lastSeenTs = root.lastSeenTs - stateFileView.writeAdapter() + stateAdapter.lastSeenTs = root.lastSeenTs; + stateFileView.writeAdapter(); } catch (e) { - Logger.e("Notifications", "Save state failed:", e) + Logger.e("Notifications", "Save state failed:", e); } } function updateLastSeenTs() { - root.lastSeenTs = Time.timestamp * 1000 - saveState() + root.lastSeenTs = Time.timestamp * 1000; + saveState(); } // Utility functions function getAppName(name) { if (!name || name.trim() === "") - return "Unknown" - name = name.trim() + return "Unknown"; + name = name.trim(); if (name.includes(".") && (name.startsWith("com.") || name.startsWith("org.") || name.startsWith("io.") || name.startsWith("net."))) { - const parts = name.split(".") - let appPart = parts[parts.length - 1] + const parts = name.split("."); + let appPart = parts[parts.length - 1]; if (!appPart || appPart === "app" || appPart === "desktop") { - appPart = parts[parts.length - 2] || parts[0] + appPart = parts[parts.length - 2] || parts[0]; } if (appPart) - name = appPart + name = appPart; } if (name.includes(".")) { - const parts = name.split(".") - let displayName = parts[parts.length - 1] + const parts = name.split("."); + let displayName = parts[parts.length - 1]; if (!displayName || /^\d+$/.test(displayName)) { - displayName = parts[parts.length - 2] || parts[0] + displayName = parts[parts.length - 2] || parts[0]; } if (displayName) { - displayName = displayName.charAt(0).toUpperCase() + displayName.slice(1) - displayName = displayName.replace(/([a-z])([A-Z])/g, '$1 $2') - displayName = displayName.replace(/app$/i, '').trim() - displayName = displayName.replace(/desktop$/i, '').trim() - displayName = displayName.replace(/flatpak$/i, '').trim() + displayName = displayName.charAt(0).toUpperCase() + displayName.slice(1); + displayName = displayName.replace(/([a-z])([A-Z])/g, '$1 $2'); + displayName = displayName.replace(/app$/i, '').trim(); + displayName = displayName.replace(/desktop$/i, '').trim(); + displayName = displayName.replace(/flatpak$/i, '').trim(); if (!displayName) { - displayName = parts[parts.length - 1].charAt(0).toUpperCase() + parts[parts.length - 1].slice(1) + displayName = parts[parts.length - 1].charAt(0).toUpperCase() + parts[parts.length - 1].slice(1); } } - return displayName || name + return displayName || name; } - let displayName = name.charAt(0).toUpperCase() + name.slice(1) - displayName = displayName.replace(/([a-z])([A-Z])/g, '$1 $2') - displayName = displayName.replace(/app$/i, '').trim() - displayName = displayName.replace(/desktop$/i, '').trim() + let displayName = name.charAt(0).toUpperCase() + name.slice(1); + displayName = displayName.replace(/([a-z])([A-Z])/g, '$1 $2'); + displayName = displayName.replace(/app$/i, '').trim(); + displayName = displayName.replace(/desktop$/i, '').trim(); - return displayName || name + return displayName || name; } function getIcon(icon) { if (!icon) - return "" + return ""; if (icon.startsWith("/") || icon.startsWith("file://")) - return icon - return ThemeIcons.iconFromName(icon) + return icon; + return ThemeIcons.iconFromName(icon); } function stripTags(text) { - return text.replace(/<[^>]*>?/gm, '') + return text.replace(/<[^>]*>?/gm, ''); } function generateImageId(notification, image) { if (image && image.startsWith("image://")) { if (image.startsWith("image://qsimage/")) { - const key = (notification.appName || "") + "|" + (notification.summary || "") - return Checksum.sha256(key) + const key = (notification.appName || "") + "|" + (notification.summary || ""); + return Checksum.sha256(key); } - return Checksum.sha256(image) + return Checksum.sha256(image); } - return "" + return ""; } function pauseTimeout(id) { - const notifData = activeNotifications[id] + const notifData = activeNotifications[id]; if (notifData && !notifData.metadata.paused) { - notifData.metadata.paused = true - notifData.metadata.pauseTime = Date.now() + notifData.metadata.paused = true; + notifData.metadata.pauseTime = Date.now(); } } function resumeTimeout(id) { - const notifData = activeNotifications[id] + const notifData = activeNotifications[id]; if (notifData && notifData.metadata.paused) { - notifData.metadata.timestamp += Date.now() - notifData.metadata.pauseTime - notifData.metadata.paused = false + notifData.metadata.timestamp += Date.now() - notifData.metadata.pauseTime; + notifData.metadata.paused = false; } } // Public API function dismissActiveNotification(id) { - activeNotifications[id]?.notification?.dismiss() - removeNotification(id) + activeNotifications[id]?.notification?.dismiss(); + removeNotification(id); } function dismissOldestActive() { if (activeList.count > 0) { - const lastNotif = activeList.get(activeList.count - 1) - dismissActiveNotification(lastNotif.id) + const lastNotif = activeList.get(activeList.count - 1); + dismissActiveNotification(lastNotif.id); } } function dismissAllActive() { for (const id in activeNotifications) { - activeNotifications[id].notification?.dismiss() - activeNotifications[id].watcher?.destroy() + activeNotifications[id].notification?.dismiss(); + activeNotifications[id].watcher?.destroy(); } - activeList.clear() - activeNotifications = {} - quickshellIdToInternalId = {} + activeList.clear(); + activeNotifications = {}; + quickshellIdToInternalId = {}; } function invokeAction(id, actionId) { - const notifData = activeNotifications[id] + const notifData = activeNotifications[id]; if (!notifData?.notification?.actions) - return false + return false; for (const action of notifData.notification.actions) { if (action.identifier === actionId && action.invoke) { - action.invoke() - return true + action.invoke(); + return true; } } - return false + return false; } function removeFromHistory(notificationId) { for (var i = 0; i < historyList.count; i++) { - const notif = historyList.get(i) + const notif = historyList.get(i); if (notif.id === notificationId) { if (notif.cachedImage && !notif.cachedImage.startsWith("image://")) { - Quickshell.execDetached(["rm", "-f", notif.cachedImage]) + Quickshell.execDetached(["rm", "-f", notif.cachedImage]); } - historyList.remove(i) - saveHistory() - return true + historyList.remove(i); + saveHistory(); + return true; } } - return false + return false; } function clearHistory() { try { - Quickshell.execDetached(["sh", "-c", `rm -rf "${Settings.cacheDirImagesNotifications}"*`]) + Quickshell.execDetached(["sh", "-c", `rm -rf "${Settings.cacheDirImagesNotifications}"*`]); } catch (e) { - Logger.e("Notifications", "Failed to clear cache directory:", e) + Logger.e("Notifications", "Failed to clear cache directory:", e); } - historyList.clear() - saveHistory() + historyList.clear(); + saveHistory(); } // Signals signal animateAndRemove(string notificationId) onDoNotDisturbChanged: { - ToastService.showNotice(doNotDisturb ? I18n.tr("toast.do-not-disturb.enabled") : I18n.tr("toast.do-not-disturb.disabled"), doNotDisturb ? I18n.tr("toast.do-not-disturb.enabled-desc") : I18n.tr("toast.do-not-disturb.disabled-desc"), doNotDisturb ? "bell-off" : "bell") + ToastService.showNotice(doNotDisturb ? I18n.tr("toast.do-not-disturb.enabled") : I18n.tr("toast.do-not-disturb.disabled"), doNotDisturb ? I18n.tr("toast.do-not-disturb.enabled-desc") : I18n.tr("toast.do-not-disturb.disabled-desc"), doNotDisturb ? "bell-off" : "bell"); } } diff --git a/Services/System/ProgramCheckerService.qml b/Services/System/ProgramCheckerService.qml index 0d2cd0c8..190c7499 100644 --- a/Services/System/ProgramCheckerService.qml +++ b/Services/System/ProgramCheckerService.qml @@ -40,29 +40,29 @@ Singleton { // Function to detect Discord client by checking config directories function detectDiscordClient() { // Build shell script to check each client - var scriptParts = ["available_clients=\"\";"] + var scriptParts = ["available_clients=\"\";"]; for (var i = 0; i < TemplateRegistry.discordClients.length; i++) { - var client = TemplateRegistry.discordClients[i] - var clientName = client.name - var configPath = client.configPath + var client = TemplateRegistry.discordClients[i]; + var clientName = client.name; + var configPath = client.configPath; // Use the actual config path from the client, removing ~ prefix - var checkPath = configPath.startsWith("~") ? configPath.substring(2) : configPath.substring(1) + var checkPath = configPath.startsWith("~") ? configPath.substring(2) : configPath.substring(1); // Check if this client requires themes folder to exist if (client.requiresThemesFolder) { - scriptParts.push("if [ -d \"$HOME/" + checkPath + "/themes\" ]; then available_clients=\"$available_clients " + clientName + "\"; fi;") + scriptParts.push("if [ -d \"$HOME/" + checkPath + "/themes\" ]; then available_clients=\"$available_clients " + clientName + "\"; fi;"); } else { - scriptParts.push("if [ -d \"$HOME/" + checkPath + "\" ]; then available_clients=\"$available_clients " + clientName + "\"; fi;") + scriptParts.push("if [ -d \"$HOME/" + checkPath + "\" ]; then available_clients=\"$available_clients " + clientName + "\"; fi;"); } } - scriptParts.push("echo \"$available_clients\"") + scriptParts.push("echo \"$available_clients\""); // Use a Process to check directory existence for all clients - discordDetector.command = ["sh", "-c", scriptParts.join(" ")] - discordDetector.running = true + discordDetector.command = ["sh", "-c", scriptParts.join(" ")]; + discordDetector.running = true; } // Process to detect Discord client directories @@ -71,32 +71,32 @@ Singleton { running: false onExited: function (exitCode) { - availableDiscordClients = [] + availableDiscordClients = []; if (exitCode === 0) { var detectedClients = stdout.text.trim().split(/\s+/).filter(function (client) { - return client.length > 0 - }) + return client.length > 0; + }); if (detectedClients.length > 0) { // Build list of available clients for (var i = 0; i < detectedClients.length; i++) { - var clientName = detectedClients[i] + var clientName = detectedClients[i]; for (var j = 0; j < TemplateRegistry.discordClients.length; j++) { - var client = TemplateRegistry.discordClients[j] + var client = TemplateRegistry.discordClients[j]; if (client.name === clientName) { - availableDiscordClients.push(client) - break + availableDiscordClients.push(client); + break; } } } - Logger.i("ProgramChecker", "Detected Discord clients:", detectedClients.join(", ")) + Logger.i("ProgramChecker", "Detected Discord clients:", detectedClients.join(", ")); } } if (availableDiscordClients.length === 0) { - Logger.d("ProgramChecker", "No Discord clients detected") + Logger.d("ProgramChecker", "No Discord clients detected"); } } @@ -107,22 +107,22 @@ Singleton { // Function to detect Code client by checking config directories function detectCodeClient() { // Build shell script to check each client - var scriptParts = ["available_clients=\"\";"] + var scriptParts = ["available_clients=\"\";"]; for (var i = 0; i < TemplateRegistry.codeClients.length; i++) { - var client = TemplateRegistry.codeClients[i] - var clientName = client.name - var configPath = client.configPath + var client = TemplateRegistry.codeClients[i]; + var clientName = client.name; + var configPath = client.configPath; // Check if the config directory exists - scriptParts.push("if [ -d \"$HOME" + configPath.substring(1) + "\" ]; then available_clients=\"$available_clients " + clientName + "\"; fi;") + scriptParts.push("if [ -d \"$HOME" + configPath.substring(1) + "\" ]; then available_clients=\"$available_clients " + clientName + "\"; fi;"); } - scriptParts.push("echo \"$available_clients\"") + scriptParts.push("echo \"$available_clients\""); // Use a Process to check directory existence for all clients - codeDetector.command = ["sh", "-c", scriptParts.join(" ")] - codeDetector.running = true + codeDetector.command = ["sh", "-c", scriptParts.join(" ")]; + codeDetector.running = true; } // Process to detect Code client directories @@ -131,32 +131,32 @@ Singleton { running: false onExited: function (exitCode) { - availableCodeClients = [] + availableCodeClients = []; if (exitCode === 0) { var detectedClients = stdout.text.trim().split(/\s+/).filter(function (client) { - return client.length > 0 - }) + return client.length > 0; + }); if (detectedClients.length > 0) { // Build list of available clients for (var i = 0; i < detectedClients.length; i++) { - var clientName = detectedClients[i] + var clientName = detectedClients[i]; for (var j = 0; j < TemplateRegistry.codeClients.length; j++) { - var client = TemplateRegistry.codeClients[j] + var client = TemplateRegistry.codeClients[j]; if (client.name === clientName) { - availableCodeClients.push(client) - break + availableCodeClients.push(client); + break; } } } - Logger.i("ProgramChecker", "Detected Code clients:", detectedClients.join(", ")) + Logger.i("ProgramChecker", "Detected Code clients:", detectedClients.join(", ")); } } if (availableCodeClients.length === 0) { - Logger.d("ProgramChecker", "No Code clients detected") + Logger.d("ProgramChecker", "No Code clients detected"); } } @@ -197,22 +197,22 @@ Singleton { onExited: function (exitCode) { // Set the availability property - root[currentProperty] = (exitCode === 0) + root[currentProperty] = (exitCode === 0); // Stop the process to free resources - running = false + running = false; // Track completion - root.completedChecks++ + root.completedChecks++; // Check next program or emit completion signal if (root.completedChecks >= root.totalChecks) { // Run Discord and Code client detection after all checks are complete - root.detectDiscordClient() - root.detectCodeClient() - root.checksCompleted() + root.detectDiscordClient(); + root.detectCodeClient(); + root.checksCompleted(); } else { - root.checkNextProgram() + root.checkNextProgram(); } } @@ -227,60 +227,59 @@ Singleton { // Function to check the next program in the queue function checkNextProgram() { if (currentCheckIndex >= checkQueue.length) - return + return; + var propertyName = checkQueue[currentCheckIndex]; + var command = programsToCheck[propertyName]; - var propertyName = checkQueue[currentCheckIndex] - var command = programsToCheck[propertyName] + checker.currentProperty = propertyName; + checker.command = command; + checker.running = true; - checker.currentProperty = propertyName - checker.command = command - checker.running = true - - currentCheckIndex++ + currentCheckIndex++; } // Function to run all program checks function checkAllPrograms() { // Reset state - completedChecks = 0 - currentCheckIndex = 0 - checkQueue = Object.keys(programsToCheck) + completedChecks = 0; + currentCheckIndex = 0; + checkQueue = Object.keys(programsToCheck); // Start first check if (checkQueue.length > 0) { - checkNextProgram() + checkNextProgram(); } } // Function to check a specific program function checkProgram(programProperty) { if (!programsToCheck.hasOwnProperty(programProperty)) { - Logger.w("ProgramChecker", "Unknown program property:", programProperty) - return + Logger.w("ProgramChecker", "Unknown program property:", programProperty); + return; } - checker.currentProperty = programProperty - checker.command = programsToCheck[programProperty] - checker.running = true + checker.currentProperty = programProperty; + checker.command = programsToCheck[programProperty]; + checker.running = true; } // Manual function to test Discord detection (for debugging) function testDiscordDetection() { - Logger.d("ProgramChecker", "Testing Discord detection...") - Logger.d("ProgramChecker", "HOME:", Quickshell.env("HOME")) + Logger.d("ProgramChecker", "Testing Discord detection..."); + Logger.d("ProgramChecker", "HOME:", Quickshell.env("HOME")); // Test each client directory for (var i = 0; i < TemplateRegistry.discordClients.length; i++) { - var client = TemplateRegistry.discordClients[i] - var configDir = client.configPath.replace("~", Quickshell.env("HOME")) - Logger.d("ProgramChecker", "Checking:", configDir) + var client = TemplateRegistry.discordClients[i]; + var configDir = client.configPath.replace("~", Quickshell.env("HOME")); + Logger.d("ProgramChecker", "Checking:", configDir); } - detectDiscordClient() + detectDiscordClient(); } // Initialize checks when service is created Component.onCompleted: { - checkAllPrograms() + checkAllPrograms(); } } diff --git a/Services/System/SystemStatService.qml b/Services/System/SystemStatService.qml index d892f97c..15b7378a 100644 --- a/Services/System/SystemStatService.qml +++ b/Services/System/SystemStatService.qml @@ -1,7 +1,7 @@ pragma Singleton +import Qt.labs.folderlistmodel import QtQuick -import Qt.labs.folderlistmodel import Quickshell import Quickshell.Io import qs.Commons @@ -42,10 +42,10 @@ Singleton { // -------------------------------------------- Component.onCompleted: { - Logger.i("SystemStat", "Service started with interval:", root.sleepDuration, "ms") + Logger.i("SystemStat", "Service started with interval:", root.sleepDuration, "ms"); // Kickoff the cpu name detection for temperature - cpuTempNameReader.checkNext() + cpuTempNameReader.checkNext(); } // -------------------------------------------- @@ -58,14 +58,14 @@ Singleton { triggeredOnStart: true onTriggered: { // Trigger all direct system files reads - memInfoFile.reload() - cpuStatFile.reload() - netDevFile.reload() + memInfoFile.reload(); + cpuStatFile.reload(); + netDevFile.reload(); // Run df (disk free) one time - dfProcess.running = true + dfProcess.running = true; - updateCpuTemperature() + updateCpuTemperature(); } } @@ -99,18 +99,18 @@ Singleton { running: false stdout: StdioCollector { onStreamFinished: { - const lines = text.trim().split('\n') - const newPercents = {} + const lines = text.trim().split('\n'); + const newPercents = {}; // Start from line 1 (skip header) for (var i = 1; i < lines.length; i++) { - const parts = lines[i].trim().split(/\s+/) + const parts = lines[i].trim().split(/\s+/); if (parts.length >= 2) { - const target = parts[0] - const percent = parseInt(parts[1].replace(/[^0-9]/g, '')) || 0 - newPercents[target] = percent + const target = parts[0]; + const percent = parseInt(parts[1].replace(/[^0-9]/g, '')) || 0; + newPercents[target] = percent; } } - root.diskPercents = newPercents + root.diskPercents = newPercents; } } } @@ -129,36 +129,36 @@ Singleton { function checkNext() { if (currentIndex >= 16) { // Check up to hwmon10 - Logger.w("No supported temperature sensor found") - return + Logger.w("No supported temperature sensor found"); + return; } //Logger.i("SystemStat", "---- Probing: hwmon", currentIndex) - cpuTempNameReader.path = `/sys/class/hwmon/hwmon${currentIndex}/name` - cpuTempNameReader.reload() + cpuTempNameReader.path = `/sys/class/hwmon/hwmon${currentIndex}/name`; + cpuTempNameReader.reload(); } onLoaded: { - const name = text().trim() + const name = text().trim(); if (root.supportedTempCpuSensorNames.includes(name)) { - root.cpuTempSensorName = name - root.cpuTempHwmonPath = `/sys/class/hwmon/hwmon${currentIndex}` - Logger.i("SystemStat", `Found ${root.cpuTempSensorName} CPU thermal sensor at ${root.cpuTempHwmonPath}`) + root.cpuTempSensorName = name; + root.cpuTempHwmonPath = `/sys/class/hwmon/hwmon${currentIndex}`; + Logger.i("SystemStat", `Found ${root.cpuTempSensorName} CPU thermal sensor at ${root.cpuTempHwmonPath}`); } else { - currentIndex++ + currentIndex++; Qt.callLater(() => { // Qt.callLater is mandatory - checkNext() - }) + checkNext(); + }); } } onLoadFailed: function (error) { - currentIndex++ + currentIndex++; Qt.callLater(() => { // Qt.callLater is mandatory - checkNext() - }) + checkNext(); + }); } } @@ -169,26 +169,26 @@ Singleton { printErrors: false onLoaded: { - const data = text().trim() + const data = text().trim(); if (root.cpuTempSensorName === "coretemp") { // For Intel, collect all temperature values - const temp = parseInt(data) / 1000.0 + const temp = parseInt(data) / 1000.0; //console.log(temp, cpuTempReader.path) - root.intelTempValues.push(temp) + root.intelTempValues.push(temp); Qt.callLater(() => { // Qt.callLater is mandatory - checkNextIntelTemp() - }) + checkNextIntelTemp(); + }); } else { // For AMD sensors (k10temp and zenpower), directly set the temperature - root.cpuTemp = Math.round(parseInt(data) / 1000.0) + root.cpuTemp = Math.round(parseInt(data) / 1000.0); } } onLoadFailed: function (error) { Qt.callLater(() => { // Qt.callLater is mandatory - checkNextIntelTemp() - }) + checkNextIntelTemp(); + }); } } @@ -197,24 +197,23 @@ Singleton { // Parse memory info from /proc/meminfo function parseMemoryInfo(text) { if (!text) - return - - const lines = text.split('\n') - let memTotal = 0 - let memAvailable = 0 + return; + const lines = text.split('\n'); + let memTotal = 0; + let memAvailable = 0; for (const line of lines) { if (line.startsWith('MemTotal:')) { - memTotal = parseInt(line.split(/\s+/)[1]) || 0 + memTotal = parseInt(line.split(/\s+/)[1]) || 0; } else if (line.startsWith('MemAvailable:')) { - memAvailable = parseInt(line.split(/\s+/)[1]) || 0 + memAvailable = parseInt(line.split(/\s+/)[1]) || 0; } } if (memTotal > 0) { - const usageKb = memTotal - memAvailable - root.memGb = (usageKb / 1048576).toFixed(1) // 1024*1024 = 1048576 - root.memPercent = Math.round((usageKb / memTotal) * 100) + const usageKb = memTotal - memAvailable; + root.memGb = (usageKb / 1048576).toFixed(1); // 1024*1024 = 1048576 + root.memPercent = Math.round((usageKb / memTotal) * 100); } } @@ -222,16 +221,14 @@ Singleton { // Calculate CPU usage from /proc/stat function calculateCpuUsage(text) { if (!text) - return - - const lines = text.split('\n') - const cpuLine = lines[0] + return; + const lines = text.split('\n'); + const cpuLine = lines[0]; // First line is total CPU if (!cpuLine.startsWith('cpu ')) - return - - const parts = cpuLine.split(/\s+/) + return; + const parts = cpuLine.split(/\s+/); const stats = { "user": parseInt(parts[1]) || 0, "nice": parseInt(parts[2]) || 0, @@ -243,23 +240,23 @@ Singleton { "steal": parseInt(parts[8]) || 0, "guest": parseInt(parts[9]) || 0, "guestNice": parseInt(parts[10]) || 0 - } - const totalIdle = stats.idle + stats.iowait - const total = Object.values(stats).reduce((sum, val) => sum + val, 0) + }; + const totalIdle = stats.idle + stats.iowait; + const total = Object.values(stats).reduce((sum, val) => sum + val, 0); if (root.prevCpuStats) { - const prevTotalIdle = root.prevCpuStats.idle + root.prevCpuStats.iowait - const prevTotal = Object.values(root.prevCpuStats).reduce((sum, val) => sum + val, 0) + const prevTotalIdle = root.prevCpuStats.idle + root.prevCpuStats.iowait; + const prevTotal = Object.values(root.prevCpuStats).reduce((sum, val) => sum + val, 0); - const diffTotal = total - prevTotal - const diffIdle = totalIdle - prevTotalIdle + const diffTotal = total - prevTotal; + const diffIdle = totalIdle - prevTotalIdle; if (diffTotal > 0) { - root.cpuUsage = (((diffTotal - diffIdle) / diffTotal) * 100).toFixed(1) + root.cpuUsage = (((diffTotal - diffIdle) / diffTotal) * 100).toFixed(1); } } - root.prevCpuStats = stats + root.prevCpuStats = stats; } // ------------------------------------------------------- @@ -267,82 +264,82 @@ Singleton { // Average speed of all interfaces excepted 'lo' function calculateNetworkSpeed(text) { if (!text) { - return + return; } - const currentTime = Date.now() / 1000 - const lines = text.split('\n') + const currentTime = Date.now() / 1000; + const lines = text.split('\n'); - let totalRx = 0 - let totalTx = 0 + let totalRx = 0; + let totalTx = 0; for (var i = 2; i < lines.length; i++) { - const line = lines[i].trim() + const line = lines[i].trim(); if (!line) { - continue + continue; } - const colonIndex = line.indexOf(':') + const colonIndex = line.indexOf(':'); if (colonIndex === -1) { - continue + continue; } - const iface = line.substring(0, colonIndex).trim() + const iface = line.substring(0, colonIndex).trim(); if (iface === 'lo') { - continue + continue; } - const statsLine = line.substring(colonIndex + 1).trim() - const stats = statsLine.split(/\s+/) + const statsLine = line.substring(colonIndex + 1).trim(); + const stats = statsLine.split(/\s+/); - const rxBytes = parseInt(stats[0], 10) || 0 - const txBytes = parseInt(stats[8], 10) || 0 + const rxBytes = parseInt(stats[0], 10) || 0; + const txBytes = parseInt(stats[8], 10) || 0; - totalRx += rxBytes - totalTx += txBytes + totalRx += rxBytes; + totalTx += txBytes; } // Compute only if we have a previous run to compare to. if (root.prevTime > 0) { - const timeDiff = currentTime - root.prevTime + const timeDiff = currentTime - root.prevTime; // Avoid division by zero if time hasn't passed. if (timeDiff > 0) { - let rxDiff = totalRx - root.prevRxBytes - let txDiff = totalTx - root.prevTxBytes + let rxDiff = totalRx - root.prevRxBytes; + let txDiff = totalTx - root.prevTxBytes; // Handle counter resets (e.g., WiFi reconnect), which would cause a negative value. if (rxDiff < 0) { - rxDiff = 0 + rxDiff = 0; } if (txDiff < 0) { - txDiff = 0 + txDiff = 0; } - root.rxSpeed = Math.round(rxDiff / timeDiff) // Speed in Bytes/s - root.txSpeed = Math.round(txDiff / timeDiff) + root.rxSpeed = Math.round(rxDiff / timeDiff); // Speed in Bytes/s + root.txSpeed = Math.round(txDiff / timeDiff); } } - root.prevRxBytes = totalRx - root.prevTxBytes = totalTx - root.prevTime = currentTime + root.prevRxBytes = totalRx; + root.prevTxBytes = totalTx; + root.prevTime = currentTime; } // ------------------------------------------------------- // Helper function to format network speeds function formatSpeed(bytesPerSecond) { if (bytesPerSecond < 1024 * 1024) { - const kb = bytesPerSecond / 1024 + const kb = bytesPerSecond / 1024; if (kb < 10) { - return kb.toFixed(1) + "KB" + return kb.toFixed(1) + "KB"; } else { - return Math.round(kb) + "KB" + return Math.round(kb) + "KB"; } } else if (bytesPerSecond < 1024 * 1024 * 1024) { - return (bytesPerSecond / (1024 * 1024)).toFixed(1) + "MB" + return (bytesPerSecond / (1024 * 1024)).toFixed(1) + "MB"; } else { - return (bytesPerSecond / (1024 * 1024 * 1024)).toFixed(1) + "GB" + return (bytesPerSecond / (1024 * 1024 * 1024)).toFixed(1) + "GB"; } } @@ -350,21 +347,21 @@ Singleton { // Compact speed formatter for vertical bar display function formatCompactSpeed(bytesPerSecond) { if (!bytesPerSecond || bytesPerSecond <= 0) - return "0" - const units = ["", "K", "M", "G"] - let value = bytesPerSecond - let unitIndex = 0 + return "0"; + const units = ["", "K", "M", "G"]; + let value = bytesPerSecond; + let unitIndex = 0; while (value >= 1024 && unitIndex < units.length - 1) { - value = value / 1024.0 - unitIndex++ + value = value / 1024.0; + unitIndex++; } // Promote at ~100 of current unit (e.g., 100k -> ~0.1M shown as 0.1M or 0M if rounded) if (unitIndex < units.length - 1 && value >= 100) { - value = value / 1024.0 - unitIndex++ + value = value / 1024.0; + unitIndex++; } - const display = Math.round(value).toString() - return display + units[unitIndex] + const display = Math.round(value).toString(); + return display + units[unitIndex]; } // ------------------------------------------------------- @@ -373,13 +370,13 @@ Singleton { // For AMD sensors (k10temp and zenpower), only use Tctl sensor // temp1_input corresponds to Tctl (Temperature Control) on these sensors if (root.cpuTempSensorName === "k10temp" || root.cpuTempSensorName === "zenpower") { - cpuTempReader.path = `${root.cpuTempHwmonPath}/temp1_input` - cpuTempReader.reload() + cpuTempReader.path = `${root.cpuTempHwmonPath}/temp1_input`; + cpuTempReader.reload(); } // For Intel coretemp, start averaging all available sensors/cores else if (root.cpuTempSensorName === "coretemp") { - root.intelTempValues = [] - root.intelTempFilesChecked = 0 - checkNextIntelTemp() + root.intelTempValues = []; + root.intelTempFilesChecked = 0; + checkNextIntelTemp(); } } @@ -389,22 +386,22 @@ Singleton { if (root.intelTempFilesChecked >= root.intelTempMaxFiles) { // Calculate average of all found temperatures if (root.intelTempValues.length > 0) { - let sum = 0 + let sum = 0; for (var i = 0; i < root.intelTempValues.length; i++) { - sum += root.intelTempValues[i] + sum += root.intelTempValues[i]; } - root.cpuTemp = Math.round(sum / root.intelTempValues.length) + root.cpuTemp = Math.round(sum / root.intelTempValues.length); //Logger.i("SystemStat", `Averaged ${root.intelTempValues.length} CPU thermal sensors: ${root.cpuTemp}°C`) } else { - Logger.w("SystemStat", "No temperature sensors found for coretemp") - root.cpuTemp = 0 + Logger.w("SystemStat", "No temperature sensors found for coretemp"); + root.cpuTemp = 0; } - return + return; } // Check next temperature file - root.intelTempFilesChecked++ - cpuTempReader.path = `${root.cpuTempHwmonPath}/temp${root.intelTempFilesChecked}_input` - cpuTempReader.reload() + root.intelTempFilesChecked++; + cpuTempReader.path = `${root.cpuTempHwmonPath}/temp${root.intelTempFilesChecked}_input`; + cpuTempReader.reload(); } } diff --git a/Services/Theming/AppThemeService.qml b/Services/Theming/AppThemeService.qml index 5bbffc82..f26c887e 100644 --- a/Services/Theming/AppThemeService.qml +++ b/Services/Theming/AppThemeService.qml @@ -16,7 +16,7 @@ Singleton { // When the wallpaper changes, regenerate with Matugen if necessary function onWallpaperChanged(screenName, path) { if (screenName === Screen.name && Settings.data.colorSchemes.useWallpaperColors) { - generateFromWallpaper() + generateFromWallpaper(); } } } @@ -24,38 +24,38 @@ Singleton { Connections { target: Settings.data.colorSchemes function onDarkModeChanged() { - Logger.i("AppThemeService", "Detected dark mode change") - generate() + Logger.i("AppThemeService", "Detected dark mode change"); + generate(); } } // PUBLIC FUNCTIONS function init() { - Logger.i("AppThemeService", "Service started") + Logger.i("AppThemeService", "Service started"); } function generate() { if (Settings.data.colorSchemes.useWallpaperColors) { - generateFromWallpaper() + generateFromWallpaper(); } else { // applyScheme will trigger template generation via schemeReader.onLoaded - ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme); } } function generateFromWallpaper() { - const wp = WallpaperService.getWallpaper(Screen.name) + const wp = WallpaperService.getWallpaper(Screen.name); if (!wp) { - Logger.e("AppThemeService", "No wallpaper found") - return + Logger.e("AppThemeService", "No wallpaper found"); + return; } - const mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - TemplateProcessor.processWallpaperColors(wp, mode) + const mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; + TemplateProcessor.processWallpaperColors(wp, mode); } function generateFromPredefinedScheme(schemeData) { - Logger.i("AppThemeService", "Generating templates from predefined color scheme") - const mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - TemplateProcessor.processPredefinedScheme(schemeData, mode) + Logger.i("AppThemeService", "Generating templates from predefined color scheme"); + const mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; + TemplateProcessor.processPredefinedScheme(schemeData, mode); } } diff --git a/Services/Theming/ColorPaletteGenerator.qml b/Services/Theming/ColorPaletteGenerator.qml index 343b1758..a9954e71 100644 --- a/Services/Theming/ColorPaletteGenerator.qml +++ b/Services/Theming/ColorPaletteGenerator.qml @@ -7,62 +7,61 @@ import "../../Helpers/ColorsConvert.js" as ColorsConvert Singleton { id: root - /** - * Generate Material Design 3 color palette from base colors - * @param colors - Object with mPrimary, mSecondary, mTertiary, mError, mSurface, etc. - * @param isDarkMode - Boolean indicating dark or light mode - * @param isStrict - Boolean; if true, use mSurfaceVariant/mOnSurfaceVariant/mOutline directly - * @returns Object with all MD3 color roles in matugen format - */ + * Generate Material Design 3 color palette from base colors + * @param colors - Object with mPrimary, mSecondary, mTertiary, mError, mSurface, etc. + * @param isDarkMode - Boolean indicating dark or light mode + * @param isStrict - Boolean; if true, use mSurfaceVariant/mOnSurfaceVariant/mOutline directly + * @returns Object with all MD3 color roles in matugen format + */ function generatePalette(colors, isDarkMode, isStrict) { const c = hex => ({ "default": { "hex": hex, "hex_stripped": hex.replace(/^#/, "") } - }) + }); // Generate container colors - const primaryContainer = ColorsConvert.generateContainerColor(colors.mPrimary, isDarkMode) - const secondaryContainer = ColorsConvert.generateContainerColor(colors.mSecondary, isDarkMode) - const tertiaryContainer = ColorsConvert.generateContainerColor(colors.mTertiary, isDarkMode) + const primaryContainer = ColorsConvert.generateContainerColor(colors.mPrimary, isDarkMode); + const secondaryContainer = ColorsConvert.generateContainerColor(colors.mSecondary, isDarkMode); + const tertiaryContainer = ColorsConvert.generateContainerColor(colors.mTertiary, isDarkMode); // Generate "on" colors - const onPrimary = ColorsConvert.generateOnColor(colors.mPrimary, isDarkMode) - const onSecondary = ColorsConvert.generateOnColor(colors.mSecondary, isDarkMode) - const onTertiary = ColorsConvert.generateOnColor(colors.mTertiary, isDarkMode) + const onPrimary = ColorsConvert.generateOnColor(colors.mPrimary, isDarkMode); + const onSecondary = ColorsConvert.generateOnColor(colors.mSecondary, isDarkMode); + const onTertiary = ColorsConvert.generateOnColor(colors.mTertiary, isDarkMode); - const onPrimaryContainer = ColorsConvert.generateOnColor(primaryContainer, isDarkMode) - const onSecondaryContainer = ColorsConvert.generateOnColor(secondaryContainer, isDarkMode) - const onTertiaryContainer = ColorsConvert.generateOnColor(tertiaryContainer, isDarkMode) + const onPrimaryContainer = ColorsConvert.generateOnColor(primaryContainer, isDarkMode); + const onSecondaryContainer = ColorsConvert.generateOnColor(secondaryContainer, isDarkMode); + const onTertiaryContainer = ColorsConvert.generateOnColor(tertiaryContainer, isDarkMode); // Generate error colors (standard red-based) - const errorContainer = ColorsConvert.generateContainerColor(colors.mError, isDarkMode) - const onError = ColorsConvert.generateOnColor(colors.mError, isDarkMode) - const onErrorContainer = ColorsConvert.generateOnColor(errorContainer, isDarkMode) + const errorContainer = ColorsConvert.generateContainerColor(colors.mError, isDarkMode); + const onError = ColorsConvert.generateOnColor(colors.mError, isDarkMode); + const onErrorContainer = ColorsConvert.generateOnColor(errorContainer, isDarkMode); // Surface is same as background in Material Design 3 - const surface = colors.mSurface - const onSurface = isStrict ? colors.mOnSurface : ColorsConvert.generateOnColor(colors.mSurface, isDarkMode) + const surface = colors.mSurface; + const onSurface = isStrict ? colors.mOnSurface : ColorsConvert.generateOnColor(colors.mSurface, isDarkMode); // Generate surface variant (slightly different tone) - const surfaceVariant = isStrict ? colors.mSurfaceVariant : ColorsConvert.adjustLightness(colors.mSurface, isDarkMode ? 5 : -3) - const onSurfaceVariant = isStrict ? colors.mOnSurfaceVariant : ColorsConvert.generateOnColor(surfaceVariant, isDarkMode) + const surfaceVariant = isStrict ? colors.mSurfaceVariant : ColorsConvert.adjustLightness(colors.mSurface, isDarkMode ? 5 : -3); + const onSurfaceVariant = isStrict ? colors.mOnSurfaceVariant : ColorsConvert.generateOnColor(surfaceVariant, isDarkMode); // Generate surface containers (progressive elevation) - const surfaceContainerLowest = ColorsConvert.generateSurfaceVariant(surface, 0, isDarkMode) - const surfaceContainerLow = ColorsConvert.generateSurfaceVariant(surface, 1, isDarkMode) - const surfaceContainer = ColorsConvert.generateSurfaceVariant(surface, 2, isDarkMode) - const surfaceContainerHigh = ColorsConvert.generateSurfaceVariant(surface, 3, isDarkMode) - const surfaceContainerHighest = ColorsConvert.generateSurfaceVariant(surface, 4, isDarkMode) + const surfaceContainerLowest = ColorsConvert.generateSurfaceVariant(surface, 0, isDarkMode); + const surfaceContainerLow = ColorsConvert.generateSurfaceVariant(surface, 1, isDarkMode); + const surfaceContainer = ColorsConvert.generateSurfaceVariant(surface, 2, isDarkMode); + const surfaceContainerHigh = ColorsConvert.generateSurfaceVariant(surface, 3, isDarkMode); + const surfaceContainerHighest = ColorsConvert.generateSurfaceVariant(surface, 4, isDarkMode); // Generate outline colors (for borders/dividers) - const outline = isStrict ? colors.mOutline : ColorsConvert.adjustLightnessAndSaturation(colors.mOnSurface, isDarkMode ? -30 : 30, isDarkMode ? -30 : 30) - const outlineVariant = ColorsConvert.adjustLightness(outline, isDarkMode ? -20 : 20) + const outline = isStrict ? colors.mOutline : ColorsConvert.adjustLightnessAndSaturation(colors.mOnSurface, isDarkMode ? -30 : 30, isDarkMode ? -30 : 30); + const outlineVariant = ColorsConvert.adjustLightness(outline, isDarkMode ? -20 : 20); // Shadow is always pitch black - const shadow = "#000000" + const shadow = "#000000"; return { "primary": c(colors.mPrimary), @@ -95,6 +94,6 @@ Singleton { "outline": c(outline), "outline_variant": c(outlineVariant), "shadow": c(shadow) - } + }; } } diff --git a/Services/Theming/ColorSchemeService.qml b/Services/Theming/ColorSchemeService.qml index a853e651..4d8505a1 100644 --- a/Services/Theming/ColorSchemeService.qml +++ b/Services/Theming/ColorSchemeService.qml @@ -1,7 +1,7 @@ pragma Singleton +import Qt.labs.folderlistmodel import QtQuick -import Qt.labs.folderlistmodel import Quickshell import Quickshell.Io import qs.Commons @@ -18,16 +18,16 @@ Singleton { Connections { target: Settings.data.colorSchemes function onDarkModeChanged() { - Logger.i("ColorScheme", "Detected dark mode change") + Logger.i("ColorScheme", "Detected dark mode change"); if (!Settings.data.colorSchemes.useWallpaperColors && Settings.data.colorSchemes.predefinedScheme) { // Re-apply current scheme to pick the right variant - applyScheme(Settings.data.colorSchemes.predefinedScheme) + applyScheme(Settings.data.colorSchemes.predefinedScheme); } // Toast: dark/light mode switched - const enabled = !!Settings.data.colorSchemes.darkMode - const label = enabled ? "Dark mode" : "Light mode" - const description = enabled ? "Enabled" : "Enabled" - ToastService.showNotice(label, description, "dark-mode") + const enabled = !!Settings.data.colorSchemes.darkMode; + const label = enabled ? "Dark mode" : "Light mode"; + const description = enabled ? "Enabled" : "Enabled"; + ToastService.showNotice(label, description, "dark-mode"); } } @@ -35,84 +35,84 @@ Singleton { function init() { // does nothing but ensure the singleton is created // do not remove - Logger.i("ColorScheme", "Service started") - loadColorSchemes() + Logger.i("ColorScheme", "Service started"); + loadColorSchemes(); } function loadColorSchemes() { - Logger.d("ColorScheme", "Load colorScheme") - scanning = true - schemes = [] + Logger.d("ColorScheme", "Load colorScheme"); + scanning = true; + schemes = []; // Use find command to locate all scheme.json files - findProcess.command = ["find", schemesDirectory, "-name", "*.json", "-type", "f"] - findProcess.running = true + findProcess.command = ["find", schemesDirectory, "-name", "*.json", "-type", "f"]; + findProcess.running = true; } function getBasename(path) { if (!path) - return "" - var chunks = path.split("/") + return ""; + var chunks = path.split("/"); // Get the filename without extension - var filename = chunks[chunks.length - 1] - var schemeName = filename.replace(".json", "") + var filename = chunks[chunks.length - 1]; + var schemeName = filename.replace(".json", ""); // Convert back to display names for special cases if (schemeName === "Noctalia-default") { - return "Noctalia (default)" + return "Noctalia (default)"; } else if (schemeName === "Noctalia-legacy") { - return "Noctalia (legacy)" + return "Noctalia (legacy)"; } else if (schemeName === "Tokyo-Night") { - return "Tokyo Night" + return "Tokyo Night"; } - return schemeName + return schemeName; } function resolveSchemePath(nameOrPath) { if (!nameOrPath) - return "" + return ""; if (nameOrPath.indexOf("/") !== -1) { - return nameOrPath + return nameOrPath; } // Handle special cases for Noctalia schemes - var schemeName = nameOrPath.replace(".json", "") + var schemeName = nameOrPath.replace(".json", ""); if (schemeName === "Noctalia (default)") { - schemeName = "Noctalia-default" + schemeName = "Noctalia-default"; } else if (schemeName === "Noctalia (legacy)") { - schemeName = "Noctalia-legacy" + schemeName = "Noctalia-legacy"; } else if (schemeName === "Tokyo Night") { - schemeName = "Tokyo-Night" + schemeName = "Tokyo-Night"; } - return schemesDirectory + "/" + schemeName + "/" + schemeName + ".json" + return schemesDirectory + "/" + schemeName + "/" + schemeName + ".json"; } function applyScheme(nameOrPath) { // Force reload by bouncing the path - var filePath = resolveSchemePath(nameOrPath) - schemeReader.path = "" - schemeReader.path = filePath + var filePath = resolveSchemePath(nameOrPath); + schemeReader.path = ""; + schemeReader.path = filePath; } function setPredefinedScheme(schemeName) { - Logger.i("ColorScheme", "Attempting to set predefined scheme to:", schemeName) + Logger.i("ColorScheme", "Attempting to set predefined scheme to:", schemeName); - var resolvedPath = resolveSchemePath(schemeName) - var basename = getBasename(schemeName) + var resolvedPath = resolveSchemePath(schemeName); + var basename = getBasename(schemeName); // Check if the scheme actually exists in the loaded schemes list - var schemeExists = false + var schemeExists = false; for (var i = 0; i < schemes.length; i++) { if (getBasename(schemes[i]) === basename) { - schemeExists = true - break + schemeExists = true; + break; } } if (schemeExists) { - Settings.data.colorSchemes.predefinedScheme = basename - applyScheme(schemeName) - ToastService.showNotice("Color Scheme", `Set to ${basename}`, "settings-color-scheme") + Settings.data.colorSchemes.predefinedScheme = basename; + applyScheme(schemeName); + ToastService.showNotice("Color Scheme", `Set to ${basename}`, "settings-color-scheme"); } else { - Logger.e("ColorScheme", "Scheme not found:", schemeName) - ToastService.showError("Color Scheme", `Scheme '${basename}' not found!`) + Logger.e("ColorScheme", "Scheme not found:", schemeName); + ToastService.showError("Color Scheme", `Scheme '${basename}' not found!`); } } @@ -122,33 +122,33 @@ Singleton { onExited: function (exitCode) { if (exitCode === 0) { - var output = stdout.text.trim() + var output = stdout.text.trim(); var files = output.split('\n').filter(function (line) { - return line.length > 0 - }) + return line.length > 0; + }); files.sort(function (a, b) { - var nameA = getBasename(a).toLowerCase() - var nameB = getBasename(b).toLowerCase() - return nameA.localeCompare(nameB) - }) - schemes = files - scanning = false - Logger.d("ColorScheme", "Listed", schemes.length, "schemes") + var nameA = getBasename(a).toLowerCase(); + var nameB = getBasename(b).toLowerCase(); + return nameA.localeCompare(nameB); + }); + schemes = files; + scanning = false; + Logger.d("ColorScheme", "Listed", schemes.length, "schemes"); // Normalize stored scheme to basename and re-apply if necessary - var stored = Settings.data.colorSchemes.predefinedScheme + var stored = Settings.data.colorSchemes.predefinedScheme; if (stored) { - var basename = getBasename(stored) + var basename = getBasename(stored); if (basename !== stored) { - Settings.data.colorSchemes.predefinedScheme = basename + Settings.data.colorSchemes.predefinedScheme = basename; } if (!Settings.data.colorSchemes.useWallpaperColors) { - applyScheme(basename) + applyScheme(basename); } } } else { - Logger.e("ColorScheme", "Failed to find color scheme files") - schemes = [] - scanning = false + Logger.e("ColorScheme", "Failed to find color scheme files"); + schemes = []; + scanning = false; } } @@ -161,48 +161,48 @@ Singleton { id: schemeReader onLoaded: { try { - var data = JSON.parse(text()) - var variant = data + var data = JSON.parse(text()); + var variant = data; // If scheme provides dark/light variants, pick based on settings if (data && (data.dark || data.light)) { if (Settings.data.colorSchemes.darkMode) { - variant = data.dark || data.light + variant = data.dark || data.light; } else { - variant = data.light || data.dark + variant = data.light || data.dark; } } - writeColorsToDisk(variant) - Logger.i("ColorScheme", "Applying color scheme:", getBasename(path)) + writeColorsToDisk(variant); + Logger.i("ColorScheme", "Applying color scheme:", getBasename(path)); // Generate Matugen templates if any are enabled and setting allows it if (Settings.data.colorSchemes.generateTemplatesForPredefined && hasEnabledTemplates()) { - AppThemeService.generateFromPredefinedScheme(data) + AppThemeService.generateFromPredefinedScheme(data); } } catch (e) { - Logger.e("ColorScheme", "Failed to parse scheme JSON:", path, e) + Logger.e("ColorScheme", "Failed to parse scheme JSON:", path, e); } } } // Check if any templates are enabled function hasEnabledTemplates() { - const templates = Settings.data.templates + const templates = Settings.data.templates; for (const key in templates) { if (templates[key]) { - return true + return true; } } - return false + return false; } // Writer to colors.json using a JsonAdapter for safety FileView { id: colorsWriter path: colorsJsonFilePath - onSaved: { + onSaved: - // Logger.i("ColorScheme", "Colors saved") - } + // Logger.i("ColorScheme", "Colors saved") + {} JsonAdapter { id: out property color mPrimary: "#000000" @@ -226,28 +226,28 @@ Singleton { function writeColorsToDisk(obj) { function pick(o, a, b, fallback) { - return (o && (o[a] || o[b])) || fallback + return (o && (o[a] || o[b])) || fallback; } - out.mPrimary = pick(obj, "mPrimary", "primary", out.mPrimary) - out.mOnPrimary = pick(obj, "mOnPrimary", "onPrimary", out.mOnPrimary) - out.mSecondary = pick(obj, "mSecondary", "secondary", out.mSecondary) - out.mOnSecondary = pick(obj, "mOnSecondary", "onSecondary", out.mOnSecondary) - out.mTertiary = pick(obj, "mTertiary", "tertiary", out.mTertiary) - out.mOnTertiary = pick(obj, "mOnTertiary", "onTertiary", out.mOnTertiary) - out.mError = pick(obj, "mError", "error", out.mError) - out.mOnError = pick(obj, "mOnError", "onError", out.mOnError) - out.mSurface = pick(obj, "mSurface", "surface", out.mSurface) - out.mOnSurface = pick(obj, "mOnSurface", "onSurface", out.mOnSurface) - out.mSurfaceVariant = pick(obj, "mSurfaceVariant", "surfaceVariant", out.mSurfaceVariant) - out.mOnSurfaceVariant = pick(obj, "mOnSurfaceVariant", "onSurfaceVariant", out.mOnSurfaceVariant) - out.mOutline = pick(obj, "mOutline", "outline", out.mOutline) - out.mShadow = pick(obj, "mShadow", "shadow", out.mShadow) - out.mHover = pick(obj, "mHover", "hover", out.mHover) - out.mOnHover = pick(obj, "mOnHover", "onHover", out.mOnHover) + out.mPrimary = pick(obj, "mPrimary", "primary", out.mPrimary); + out.mOnPrimary = pick(obj, "mOnPrimary", "onPrimary", out.mOnPrimary); + out.mSecondary = pick(obj, "mSecondary", "secondary", out.mSecondary); + out.mOnSecondary = pick(obj, "mOnSecondary", "onSecondary", out.mOnSecondary); + out.mTertiary = pick(obj, "mTertiary", "tertiary", out.mTertiary); + out.mOnTertiary = pick(obj, "mOnTertiary", "onTertiary", out.mOnTertiary); + out.mError = pick(obj, "mError", "error", out.mError); + out.mOnError = pick(obj, "mOnError", "onError", out.mOnError); + out.mSurface = pick(obj, "mSurface", "surface", out.mSurface); + out.mOnSurface = pick(obj, "mOnSurface", "onSurface", out.mOnSurface); + out.mSurfaceVariant = pick(obj, "mSurfaceVariant", "surfaceVariant", out.mSurfaceVariant); + out.mOnSurfaceVariant = pick(obj, "mOnSurfaceVariant", "onSurfaceVariant", out.mOnSurfaceVariant); + out.mOutline = pick(obj, "mOutline", "outline", out.mOutline); + out.mShadow = pick(obj, "mShadow", "shadow", out.mShadow); + out.mHover = pick(obj, "mHover", "hover", out.mHover); + out.mOnHover = pick(obj, "mOnHover", "onHover", out.mOnHover); // Force a rewrite by updating the path - colorsWriter.path = "" - colorsWriter.path = colorsJsonFilePath - colorsWriter.writeAdapter() + colorsWriter.path = ""; + colorsWriter.path = colorsJsonFilePath; + colorsWriter.writeAdapter(); } } diff --git a/Services/Theming/TemplateProcessor.qml b/Services/Theming/TemplateProcessor.qml index ba0400f1..f74f536d 100644 --- a/Services/Theming/TemplateProcessor.qml +++ b/Services/Theming/TemplateProcessor.qml @@ -26,78 +26,75 @@ Singleton { "wezterm": "~/.config/wezterm/colors/Noctalia.toml" }) - /** - * Process wallpaper colors using matugen CLI - * Dual-path architecture (wallpaper uses matugen CLI) - */ + * Process wallpaper colors using matugen CLI + * Dual-path architecture (wallpaper uses matugen CLI) + */ function processWallpaperColors(wallpaperPath, mode) { - const content = buildMatugenConfig() + const content = buildMatugenConfig(); if (!content) - return + return; + const wp = wallpaperPath.replace(/'/g, "'\\''"); + const script = buildMatugenScript(content, wp, mode); - const wp = wallpaperPath.replace(/'/g, "'\\''") - const script = buildMatugenScript(content, wp, mode) - - generateProcess.generator = "matugen" - generateProcess.command = ["bash", "-lc", script] - generateProcess.running = true + generateProcess.generator = "matugen"; + generateProcess.command = ["bash", "-lc", script]; + generateProcess.running = true; } - /** - * Process predefined color scheme using sed scripts - * Dual-path architecture (predefined uses sed scripts) - */ + * Process predefined color scheme using sed scripts + * Dual-path architecture (predefined uses sed scripts) + */ function processPredefinedScheme(schemeData, mode) { - handleTerminalThemes(mode) + handleTerminalThemes(mode); - const colors = schemeData[mode] - let script = processAllTemplates(colors, mode) + const colors = schemeData[mode]; + let script = processAllTemplates(colors, mode); // Add user templates if enabled (requirement #1) - script += buildUserTemplateCommandForPredefined(schemeData, mode) + script += buildUserTemplateCommandForPredefined(schemeData, mode); - generateProcess.generator = "predefined" - generateProcess.command = ["bash", "-lc", script] - generateProcess.running = true + generateProcess.generator = "predefined"; + generateProcess.command = ["bash", "-lc", script]; + generateProcess.running = true; } // ================================================================================ // WALLPAPER-BASED GENERATION (matugen CLI) // ================================================================================ function buildMatugenConfig() { - var lines = [] - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var lines = []; + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"; if (Settings.data.colorSchemes.useWallpaperColors) { - addWallpaperTemplates(lines, mode) + addWallpaperTemplates(lines, mode); } - addApplicationTemplates(lines, mode) + addApplicationTemplates(lines, mode); if (lines.length > 0) { - return ["[config]"].concat(lines).join("\n") + "\n" + return ["[config]"].concat(lines).join("\n") + "\n"; } - return "" + return ""; } function addWallpaperTemplates(lines, mode) { // Noctalia colors JSON - lines.push("[templates.noctalia]") - lines.push('input_path = "' + Quickshell.shellDir + '/Assets/MatugenTemplates/noctalia.json"') - lines.push('output_path = "' + Settings.configDir + 'colors.json"') + lines.push("[templates.noctalia]"); + lines.push('input_path = "' + Quickshell.shellDir + '/Assets/MatugenTemplates/noctalia.json"'); + lines.push('output_path = "' + Settings.configDir + 'colors.json"'); // Terminal templates TemplateRegistry.terminals.forEach(terminal => { if (Settings.data.templates[terminal.id]) { - lines.push(`\n[templates.${terminal.id}]`) - lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${terminal.matugenPath}"`) - lines.push(`output_path = "${terminal.outputPath}"`) - const postHook = terminal.postHook || `${TemplateRegistry.colorsApplyScript} ${terminal.id}` - lines.push(`post_hook = "${postHook}"`) + lines.push(`\n[templates.${terminal.id}]`); + lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${terminal.matugenPath}"`); + lines.push(`output_path = "${terminal.outputPath}"`); + const postHook = terminal.postHook || `${TemplateRegistry.colorsApplyScript} ${terminal.id}`; + lines.push(`post_hook = "${postHook}"`); } - }) + }); } function addApplicationTemplates(lines, mode) { @@ -108,11 +105,11 @@ Singleton { app.clients.forEach(client => { // Check if this specific client is detected if (isDiscordClientEnabled(client.name)) { - lines.push(`\n[templates.discord_${client.name}]`) - lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`) - lines.push(`output_path = "${client.path}/themes/noctalia.theme.css"`) + lines.push(`\n[templates.discord_${client.name}]`); + lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`); + lines.push(`output_path = "${client.path}/themes/noctalia.theme.css"`); } - }) + }); } } else if (app.id === "code") { // Handle Code clients specially @@ -120,221 +117,219 @@ Singleton { app.clients.forEach(client => { // Check if this specific client is detected if (isCodeClientEnabled(client.name)) { - lines.push(`\n[templates.code_${client.name}]`) - lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`) - lines.push(`output_path = "${client.path}"`) + lines.push(`\n[templates.code_${client.name}]`); + lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`); + lines.push(`output_path = "${client.path}"`); } - }) + }); } } else { // Handle regular apps if (Settings.data.templates[app.id]) { app.outputs.forEach((output, idx) => { - lines.push(`\n[templates.${app.id}_${idx}]`) - lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`) - lines.push(`output_path = "${output.path}"`) + lines.push(`\n[templates.${app.id}_${idx}]`); + lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`); + lines.push(`output_path = "${output.path}"`); if (app.postProcess) { - lines.push(`post_hook = "${app.postProcess(mode)}"`) + lines.push(`post_hook = "${app.postProcess(mode)}"`); } - }) + }); } } - }) + }); } function isDiscordClientEnabled(clientName) { // Check ProgramCheckerService to see if client is detected for (var i = 0; i < ProgramCheckerService.availableDiscordClients.length; i++) { if (ProgramCheckerService.availableDiscordClients[i].name === clientName) { - return true + return true; } } - return false + return false; } function isCodeClientEnabled(clientName) { // Check ProgramCheckerService to see if client is detected for (var i = 0; i < ProgramCheckerService.availableCodeClients.length; i++) { if (ProgramCheckerService.availableCodeClients[i].name === clientName) { - return true + return true; } } - return false + return false; } function buildMatugenScript(content, wallpaper, mode) { - const delimiter = "MATUGEN_CONFIG_EOF_" + Math.random().toString(36).substr(2, 9) - const pathEsc = dynamicConfigPath.replace(/'/g, "'\\''") + const delimiter = "MATUGEN_CONFIG_EOF_" + Math.random().toString(36).substr(2, 9); + const pathEsc = dynamicConfigPath.replace(/'/g, "'\\''"); - let script = `cat > '${pathEsc}' << '${delimiter}'\n${content}\n${delimiter}\n` - script += `matugen image '${wallpaper}' --config '${pathEsc}' --mode ${mode} --type ${Settings.data.colorSchemes.matugenSchemeType}` - script += buildUserTemplateCommand(wallpaper, mode) + let script = `cat > '${pathEsc}' << '${delimiter}'\n${content}\n${delimiter}\n`; + script += `matugen image '${wallpaper}' --config '${pathEsc}' --mode ${mode} --type ${Settings.data.colorSchemes.matugenSchemeType}`; + script += buildUserTemplateCommand(wallpaper, mode); - return script + "\n" + return script + "\n"; } // ================================================================================ // PREDEFINED SCHEME GENERATION (sed scripts) // ================================================================================ function processAllTemplates(colors, mode) { - let script = "" - const homeDir = Quickshell.env("HOME") + let script = ""; + const homeDir = Quickshell.env("HOME"); TemplateRegistry.applications.forEach(app => { if (app.id === "discord") { if (Settings.data.templates.discord) { - script += processDiscordClients(app, colors, mode, homeDir) + script += processDiscordClients(app, colors, mode, homeDir); } } else if (app.id === "code") { if (Settings.data.templates.code) { - script += processCodeClients(app, colors, mode, homeDir) + script += processCodeClients(app, colors, mode, homeDir); } } else { if (Settings.data.templates[app.id]) { - script += processTemplate(app, colors, mode, homeDir) + script += processTemplate(app, colors, mode, homeDir); } } - }) - return script + }); + return script; } function processDiscordClients(discordApp, colors, mode, homeDir) { - let script = "" - const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, false) + let script = ""; + const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, false); discordApp.clients.forEach(client => { if (!isDiscordClientEnabled(client.name)) - return + return; + const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${discordApp.input}`; + const outputPath = `${client.path}/themes/noctalia.theme.css`.replace("~", homeDir); + const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')); + const baseConfigDir = outputDir.replace("/themes", ""); - const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${discordApp.input}` - const outputPath = `${client.path}/themes/noctalia.theme.css`.replace("~", homeDir) - const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')) - const baseConfigDir = outputDir.replace("/themes", "") + script += `\n`; + script += `if [ -d "${baseConfigDir}" ]; then\n`; + script += ` mkdir -p ${outputDir}\n`; + script += ` cp '${templatePath}' '${outputPath}'\n`; + script += ` ${replaceColorsInFile(outputPath, palette)}`; + script += `else\n`; + script += ` echo "Discord client ${client.name} not found at ${baseConfigDir}, skipping"\n`; + script += `fi\n`; + }); - script += `\n` - script += `if [ -d "${baseConfigDir}" ]; then\n` - script += ` mkdir -p ${outputDir}\n` - script += ` cp '${templatePath}' '${outputPath}'\n` - script += ` ${replaceColorsInFile(outputPath, palette)}` - script += `else\n` - script += ` echo "Discord client ${client.name} not found at ${baseConfigDir}, skipping"\n` - script += `fi\n` - }) - - return script + return script; } function processCodeClients(codeApp, colors, mode, homeDir) { - let script = "" - const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, false) + let script = ""; + const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, false); codeApp.clients.forEach(client => { if (!isCodeClientEnabled(client.name)) - return - - const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${codeApp.input}` - const outputPath = client.path.replace("~", homeDir) - const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')) + return; + const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${codeApp.input}`; + const outputPath = client.path.replace("~", homeDir); + const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')); // Extract base config directory for checking - var baseConfigDir = "" + var baseConfigDir = ""; if (client.name === "code") { - baseConfigDir = "~/.vscode".replace("~", homeDir) + baseConfigDir = "~/.vscode".replace("~", homeDir); } else if (client.name === "codium") { - baseConfigDir = "~/.vscode-oss".replace("~", homeDir) + baseConfigDir = "~/.vscode-oss".replace("~", homeDir); } - script += `\n` - script += `if [ -d "${baseConfigDir}" ]; then\n` - script += ` mkdir -p ${outputDir}\n` - script += ` cp '${templatePath}' '${outputPath}'\n` - script += ` ${replaceColorsInFile(outputPath, palette)}` - script += `else\n` - script += ` echo "Code client ${client.name} not found at ${baseConfigDir}, skipping"\n` - script += `fi\n` - }) + script += `\n`; + script += `if [ -d "${baseConfigDir}" ]; then\n`; + script += ` mkdir -p ${outputDir}\n`; + script += ` cp '${templatePath}' '${outputPath}'\n`; + script += ` ${replaceColorsInFile(outputPath, palette)}`; + script += `else\n`; + script += ` echo "Code client ${client.name} not found at ${baseConfigDir}, skipping"\n`; + script += `fi\n`; + }); - return script + return script; } function processTemplate(app, colors, mode, homeDir) { - const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, app.strict || false) - let script = "" + const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, app.strict || false); + let script = ""; app.outputs.forEach(output => { - const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}` - const outputPath = output.path.replace("~", homeDir) - const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')) + const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}`; + const outputPath = output.path.replace("~", homeDir); + const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')); - script += `\n` - script += `mkdir -p ${outputDir}\n` - script += `cp '${templatePath}' '${outputPath}'\n` - script += replaceColorsInFile(outputPath, palette) - script += `\n` - }) + script += `\n`; + script += `mkdir -p ${outputDir}\n`; + script += `cp '${templatePath}' '${outputPath}'\n`; + script += replaceColorsInFile(outputPath, palette); + script += `\n`; + }); if (app.postProcess) { - script += app.postProcess(mode) + script += app.postProcess(mode); } - return script + return script; } function replaceColorsInFile(filePath, colors) { - let script = "" + let script = ""; Object.keys(colors).forEach(colorKey => { - const hexValue = colors[colorKey].default.hex - const hexStrippedValue = colors[colorKey].default.hex_stripped + const hexValue = colors[colorKey].default.hex; + const hexStrippedValue = colors[colorKey].default.hex_stripped; - const escapedHex = hexValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - const escapedHexStripped = hexStrippedValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + const escapedHex = hexValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const escapedHexStripped = hexStrippedValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // replace hex_stripped - script += `sed -i 's/{{colors\\.${colorKey}\\.default\\.hex_stripped}}/${escapedHexStripped}/g' '${filePath}'\n` + script += `sed -i 's/{{colors\\.${colorKey}\\.default\\.hex_stripped}}/${escapedHexStripped}/g' '${filePath}'\n`; // replace hex - script += `sed -i 's/{{colors\\.${colorKey}\\.default\\.hex}}/${escapedHex}/g' '${filePath}'\n` - }) - return script + script += `sed -i 's/{{colors\\.${colorKey}\\.default\\.hex}}/${escapedHex}/g' '${filePath}'\n`; + }); + return script; } // ================================================================================ // TERMINAL THEMES (predefined schemes use pre-rendered files) // ================================================================================ function handleTerminalThemes(mode) { - const commands = [] - const homeDir = Quickshell.env("HOME") + const commands = []; + const homeDir = Quickshell.env("HOME"); Object.keys(terminalPaths).forEach(terminal => { if (Settings.data.templates[terminal]) { - const outputPath = terminalPaths[terminal].replace("~", homeDir) - const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')) - const templatePath = getTerminalColorsTemplate(terminal, mode) + const outputPath = terminalPaths[terminal].replace("~", homeDir); + const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')); + const templatePath = getTerminalColorsTemplate(terminal, mode); - commands.push(`mkdir -p ${outputDir}`) - commands.push(`cp -f ${templatePath} ${outputPath}`) - commands.push(`${TemplateRegistry.colorsApplyScript} ${terminal}`) + commands.push(`mkdir -p ${outputDir}`); + commands.push(`cp -f ${templatePath} ${outputPath}`); + commands.push(`${TemplateRegistry.colorsApplyScript} ${terminal}`); } - }) + }); if (commands.length > 0) { - copyProcess.command = ["bash", "-lc", commands.join('; ')] - copyProcess.running = true + copyProcess.command = ["bash", "-lc", commands.join('; ')]; + copyProcess.running = true; } } function getTerminalColorsTemplate(terminal, mode) { - let colorScheme = Settings.data.colorSchemes.predefinedScheme - colorScheme = schemeNameMap[colorScheme] || colorScheme + let colorScheme = Settings.data.colorSchemes.predefinedScheme; + colorScheme = schemeNameMap[colorScheme] || colorScheme; - let extension = "" + let extension = ""; if (terminal === 'kitty') { - extension = ".conf" + extension = ".conf"; } else if (terminal === 'wezterm') { - extension = ".toml" + extension = ".toml"; } - return `${Quickshell.shellDir}/Assets/ColorScheme/${colorScheme}/terminal/${terminal}/${colorScheme}-${mode}${extension}` + return `${Quickshell.shellDir}/Assets/ColorScheme/${colorScheme}/terminal/${terminal}/${colorScheme}-${mode}${extension}`; } // ================================================================================ @@ -342,43 +337,43 @@ Singleton { // ================================================================================ function buildUserTemplateCommand(input, mode) { if (!Settings.data.templates.enableUserTemplates) - return "" + return ""; - const userConfigPath = getUserConfigPath() - let script = "\n# Execute user config if it exists\n" - script += `if [ -f '${userConfigPath}' ]; then\n` - script += ` matugen image '${input}' --config '${userConfigPath}' --mode ${mode} --type ${Settings.data.colorSchemes.matugenSchemeType}\n` - script += "fi" + const userConfigPath = getUserConfigPath(); + let script = "\n# Execute user config if it exists\n"; + script += `if [ -f '${userConfigPath}' ]; then\n`; + script += ` matugen image '${input}' --config '${userConfigPath}' --mode ${mode} --type ${Settings.data.colorSchemes.matugenSchemeType}\n`; + script += "fi"; - return script + return script; } function buildUserTemplateCommandForPredefined(schemeData, mode) { if (!Settings.data.templates.enableUserTemplates) - return "" + return ""; - const userConfigPath = getUserConfigPath() - const colors = schemeData[mode] - const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, false) + const userConfigPath = getUserConfigPath(); + const colors = schemeData[mode]; + const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, false); - const tempJsonPath = Settings.cacheDir + "predefined-colors.json" - const tempJsonPathEsc = tempJsonPath.replace(/'/g, "'\\''") + const tempJsonPath = Settings.cacheDir + "predefined-colors.json"; + const tempJsonPathEsc = tempJsonPath.replace(/'/g, "'\\''"); - let script = "\n# Execute user templates with predefined scheme colors\n" - script += `if [ -f '${userConfigPath}' ]; then\n` - script += ` cat > '${tempJsonPathEsc}' << 'EOF'\n` + let script = "\n# Execute user templates with predefined scheme colors\n"; + script += `if [ -f '${userConfigPath}' ]; then\n`; + script += ` cat > '${tempJsonPathEsc}' << 'EOF'\n`; script += JSON.stringify({ "colors": palette - }, null, 2) + "\n" - script += "EOF\n" - script += ` matugen json '${tempJsonPathEsc}' --config '${userConfigPath}' --mode ${mode}\n` - script += "fi" + }, null, 2) + "\n"; + script += "EOF\n"; + script += ` matugen json '${tempJsonPathEsc}' --config '${userConfigPath}' --mode ${mode}\n`; + script += "fi"; - return script + return script; } function getUserConfigPath() { - return (Settings.configDir + "user-templates.toml").replace(/'/g, "'\\''") + return (Settings.configDir + "user-templates.toml").replace(/'/g, "'\\''"); } // ================================================================================ @@ -393,30 +388,30 @@ Singleton { property string generator: "" function buildErrorMessage() { - const description = (stderr.text && stderr.text.trim() !== "") ? stderr.text.trim() : ((stdout.text && stdout.text.trim() !== "") ? stdout.text.trim() : I18n.tr("toast.theming-processor-failed.desc-generic")) - const title = I18n.tr(`toast.theming-processor-failed.title-${generator}`) - return description + const description = (stderr.text && stderr.text.trim() !== "") ? stderr.text.trim() : ((stdout.text && stdout.text.trim() !== "") ? stdout.text.trim() : I18n.tr("toast.theming-processor-failed.desc-generic")); + const title = I18n.tr(`toast.theming-processor-failed.title-${generator}`); + return description; } onExited: function (exitCode) { if (exitCode !== 0) { - const description = generateProcess.buildErrorMessage() - Logger.e("TemplateProcessor", "Process failed with exit code", exitCode, description) + const description = generateProcess.buildErrorMessage(); + Logger.e("TemplateProcessor", "Process failed with exit code", exitCode, description); } } stdout: StdioCollector { onStreamFinished: { if (this.text) - Logger.d("TemplateProcessor", "stdout:", this.text) + Logger.d("TemplateProcessor", "stdout:", this.text); } } stderr: StdioCollector { onStreamFinished: { if (this.text) { - const description = generateProcess.buildErrorMessage() - Logger.e("TemplateProcessor", "Process failed", description) + const description = generateProcess.buildErrorMessage(); + Logger.e("TemplateProcessor", "Process failed", description); } } } @@ -430,7 +425,7 @@ Singleton { stderr: StdioCollector { onStreamFinished: { if (this.text) { - Logger.e("TemplateProcessor", "copyProcess stderr:", this.text) + Logger.e("TemplateProcessor", "copyProcess stderr:", this.text); } } } diff --git a/Services/Theming/TemplateRegistry.qml b/Services/Theming/TemplateRegistry.qml index 2a9d2e6b..4322ba44 100644 --- a/Services/Theming/TemplateRegistry.qml +++ b/Services/Theming/TemplateRegistry.qml @@ -11,164 +11,210 @@ Singleton { readonly property string colorsApplyScript: Quickshell.shellDir + '/Bin/colors-apply.sh' // Terminal configurations (for wallpaper-based matugen templates) - readonly property var terminals: [{ + readonly property var terminals: [ + { "id": "foot", "name": "Foot", "matugenPath": "Terminal/foot", "outputPath": "~/.config/foot/themes/noctalia" - }, { + }, + { "id": "ghostty", "name": "Ghostty", "matugenPath": "Terminal/ghostty", "outputPath": "~/.config/ghostty/themes/noctalia", "postHook": "bash -c 'pgrep -f ghostty >/dev/null && pkill -SIGUSR2 ghostty || true'" - }, { + }, + { "id": "kitty", "name": "Kitty", "matugenPath": "Terminal/kitty.conf", "outputPath": "~/.config/kitty/themes/noctalia.conf" - }, { + }, + { "id": "alacritty", "name": "Alacritty", "matugenPath": "Terminal/alacritty.toml", "outputPath": "~/.config/alacritty/themes/noctalia.toml" - }, { + }, + { "id": "wezterm", "name": "Wezterm", "matugenPath": "Terminal/wezterm.toml", "outputPath": "~/.config/wezterm/colors/Noctalia.toml", "postHook": "touch ~/.config/wezterm/wezterm.lua" - }] + } + ] // Application configurations - consolidated from MatugenTemplates + AppThemeService - readonly property var applications: [{ + readonly property var applications: [ + { "id": "gtk", "name": "GTK", "category": "ui", "input": "gtk.css", - "outputs": [{ + "outputs": [ + { "path": "~/.config/gtk-3.0/gtk.css" - }, { + }, + { "path": "~/.config/gtk-4.0/gtk.css" - }], + } + ], "postProcess": mode => `gsettings set org.gnome.desktop.interface color-scheme prefer-${mode}` - }, { + }, + { "id": "qt", "name": "Qt", "category": "ui", "input": "qtct.conf", - "outputs": [{ + "outputs": [ + { "path": "~/.config/qt5ct/colors/noctalia.conf" - }, { + }, + { "path": "~/.config/qt6ct/colors/noctalia.conf" - }] - }, { + } + ] + }, + { "id": "kcolorscheme", "name": "KColorScheme", "category": "ui", "input": "kcolorscheme.colors", - "outputs": [{ + "outputs": [ + { "path": "~/.local/share/color-schemes/noctalia.colors" - }] - }, { + } + ] + }, + { "id": "fuzzel", "name": "Fuzzel", "category": "launchers", "input": "fuzzel.conf", - "outputs": [{ + "outputs": [ + { "path": "~/.config/fuzzel/themes/noctalia" - }], + } + ], "postProcess": () => `${colorsApplyScript} fuzzel` - }, { + }, + { "id": "vicinae", "name": "Vicinae", "category": "launchers", "input": "vicinae.toml", - "outputs": [{ + "outputs": [ + { "path": "~/.local/share/vicinae/themes/matugen.toml" - }], + } + ], "postProcess": () => `cp --update=none ${Quickshell.shellDir}/Assets/noctalia.svg ~/.local/share/vicinae/themes/noctalia.svg && ${colorsApplyScript} vicinae` - }, { + }, + { "id": "walker", "name": "Walker", "category": "launchers", "input": "walker.css", - "outputs": [{ + "outputs": [ + { "path": "~/.config/walker/themes/noctalia/style.css" - }], + } + ], "postProcess": () => `${colorsApplyScript} walker`, "strict": true // Use strict mode for palette generation (preserves custom surface/outline values) - }, { + }, + { "id": "pywalfox", "name": "Pywalfox", "category": "applications", "input": "pywalfox.json", - "outputs": [{ + "outputs": [ + { "path": "~/.cache/wal/colors.json" - }], + } + ], "postProcess": () => `${colorsApplyScript} pywalfox` - }, // CONSOLIDATED DISCORD CLIENTS + } // CONSOLIDATED DISCORD CLIENTS + , { "id": "discord", "name": "Discord", "category": "applications", "input": "vesktop.css", - "clients": [{ + "clients": [ + { "name": "vesktop", "path": "~/.config/vesktop", "requiresThemesFolder": false - }, { + }, + { "name": "webcord", "path": "~/.config/webcord", "requiresThemesFolder": false - }, { + }, + { "name": "armcord", "path": "~/.config/armcord", "requiresThemesFolder": false - }, { + }, + { "name": "equibop", "path": "~/.config/equibop", "requiresThemesFolder": false - }, { + }, + { "name": "lightcord", "path": "~/.config/lightcord", "requiresThemesFolder": false - }, { + }, + { "name": "dorion", "path": "~/.config/dorion", "requiresThemesFolder": false - }, { + }, + { "name": "vencord", "path": "~/.config/Vencord", "requiresThemesFolder": false - }] - }, { + } + ] + }, + { "id": "code", "name": "VSCode", "category": "applications", "input": "code.json", - "clients": [{ + "clients": [ + { "name": "code", "path": "~/.vscode/extensions/hyprluna.hyprluna-theme-1.0.2/themes/hyprluna.json" - }, { + }, + { "name": "codium", "path": "~/.vscode-oss/extensions/hyprluna.hyprluna-theme-1.0.2/themes/hyprluna.json" - }] - }, { + } + ] + }, + { "id": "spicetify", "name": "Spicetify", "category": "applications", "input": "spicetify.ini", - "outputs": [{ + "outputs": [ + { "path": "~/.config/spicetify/Themes/Comfy/color.ini" - }], + } + ], "postProcess": () => `spicetify -q apply --no-restart` - }] + } + ] // Extract Discord clients for ProgramCheckerService compatibility readonly property var discordClients: { - var clients = [] - var discordApp = applications.find(app => app.id === "discord") + var clients = []; + var discordApp = applications.find(app => app.id === "discord"); if (discordApp && discordApp.clients) { discordApp.clients.forEach(client => { clients.push({ @@ -176,87 +222,87 @@ Singleton { "configPath": client.path, "themePath": `${client.path}/themes/noctalia.theme.css`, "requiresThemesFolder": client.requiresThemesFolder || false - }) - }) + }); + }); } - return clients + return clients; } // Extract Code clients for ProgramCheckerService compatibility readonly property var codeClients: { - var clients = [] - var codeApp = applications.find(app => app.id === "code") + var clients = []; + var codeApp = applications.find(app => app.id === "code"); if (codeApp && codeApp.clients) { codeApp.clients.forEach(client => { // Extract base config directory from theme path - var themePath = client.path - var baseConfigDir = "" + var themePath = client.path; + var baseConfigDir = ""; if (client.name === "code") { // For VSCode: ~/.vscode/extensions/... -> ~/.vscode - baseConfigDir = "~/.vscode" + baseConfigDir = "~/.vscode"; } else if (client.name === "codium") { // For VSCodium: ~/.vscode-oss/extensions/... -> ~/.vscode-oss - baseConfigDir = "~/.vscode-oss" + baseConfigDir = "~/.vscode-oss"; } clients.push({ "name": client.name, "configPath": baseConfigDir, "themePath": themePath, "requiresThemesFolder": false - }) - }) + }); + }); } - return clients + return clients; } // Build user templates TOML content function buildUserTemplatesToml() { - var lines = [] - lines.push("[config]") - lines.push("") - lines.push("[templates]") - lines.push("") - lines.push("# User-defined templates") - lines.push("# Add your custom templates below") - lines.push("# Example:") - lines.push("# [templates.myapp]") - lines.push("# input_path = \"~/.config/noctalia/templates/myapp.css\"") - lines.push("# output_path = \"~/.config/myapp/theme.css\"") - lines.push("# post_hook = \"myapp --reload-theme\"") - lines.push("") - lines.push("# Remove this section and add your own templates") - lines.push("#[templates.placeholder]") - lines.push("#input_path = \"" + Quickshell.shellDir + "/Assets/MatugenTemplates/noctalia.json\"") - lines.push("#output_path = \"" + Settings.cacheDir + "placeholder.json\"") - lines.push("") + var lines = []; + lines.push("[config]"); + lines.push(""); + lines.push("[templates]"); + lines.push(""); + lines.push("# User-defined templates"); + lines.push("# Add your custom templates below"); + lines.push("# Example:"); + lines.push("# [templates.myapp]"); + lines.push("# input_path = \"~/.config/noctalia/templates/myapp.css\""); + lines.push("# output_path = \"~/.config/myapp/theme.css\""); + lines.push("# post_hook = \"myapp --reload-theme\""); + lines.push(""); + lines.push("# Remove this section and add your own templates"); + lines.push("#[templates.placeholder]"); + lines.push("#input_path = \"" + Quickshell.shellDir + "/Assets/MatugenTemplates/noctalia.json\""); + lines.push("#output_path = \"" + Settings.cacheDir + "placeholder.json\""); + lines.push(""); - return lines.join("\n") + "\n" + return lines.join("\n") + "\n"; } // Write user templates TOML file (moved from MatugenTemplates) function writeUserTemplatesToml() { - var userConfigPath = Settings.configDir + "user-templates.toml" + var userConfigPath = Settings.configDir + "user-templates.toml"; // Check if file already exists - fileCheckProcess.command = ["test", "-f", userConfigPath] - fileCheckProcess.running = true + fileCheckProcess.command = ["test", "-f", userConfigPath]; + fileCheckProcess.running = true; } function doWriteUserTemplatesToml() { - var userConfigPath = Settings.configDir + "user-templates.toml" - var configContent = buildUserTemplatesToml() - var userConfigPathEsc = userConfigPath.replace(/'/g, "'\\''") + var userConfigPath = Settings.configDir + "user-templates.toml"; + var configContent = buildUserTemplatesToml(); + var userConfigPathEsc = userConfigPath.replace(/'/g, "'\\''"); // Ensure directory exists (should already exist but just in case) - Quickshell.execDetached(["mkdir", "-p", Settings.configDir]) + Quickshell.execDetached(["mkdir", "-p", Settings.configDir]); // Write the config file using heredoc to avoid escaping issues - var script = `cat > '${userConfigPathEsc}' << 'EOF'\n` - script += configContent - script += "EOF\n" - Quickshell.execDetached(["sh", "-c", script]) + var script = `cat > '${userConfigPathEsc}' << 'EOF'\n`; + script += configContent; + script += "EOF\n"; + Quickshell.execDetached(["sh", "-c", script]); - Logger.d("TemplateRegistry", "User templates config written to:", userConfigPath) + Logger.d("TemplateRegistry", "User templates config written to:", userConfigPath); } // Process for checking if user templates file exists @@ -267,10 +313,10 @@ Singleton { onExited: function (exitCode) { if (exitCode === 0) { // File exists, skip creation - Logger.d("TemplateRegistry", "User templates config already exists, skipping creation") + Logger.d("TemplateRegistry", "User templates config already exists, skipping creation"); } else { // File doesn't exist, create it - doWriteUserTemplatesToml() + doWriteUserTemplatesToml(); } } } diff --git a/Services/UI/BarService.qml b/Services/UI/BarService.qml index 51dd733a..b2c40fa0 100644 --- a/Services/UI/BarService.qml +++ b/Services/UI/BarService.qml @@ -29,43 +29,43 @@ Singleton { interval: 100 repeat: false onTriggered: { - hasAudioVisualizer = false + hasAudioVisualizer = false; if (getAllWidgetInstances("AudioVisualizer").length > 0) { - hasAudioVisualizer = true - return + hasAudioVisualizer = true; + return; } - const widgets = getAllWidgetInstances("MediaMini") + const widgets = getAllWidgetInstances("MediaMini"); for (var i = 0; i < widgets.length; i++) { - const widget = widgets[i] + const widget = widgets[i]; if (widget.showVisualizer) { - hasAudioVisualizer = true - return + hasAudioVisualizer = true; + return; } } } } Component.onCompleted: { - Logger.i("BarService", "Service started") + Logger.i("BarService", "Service started"); } // Function for the Bar to call when it's ready function registerBar(screenName) { if (!readyBars[screenName]) { - readyBars[screenName] = true - Logger.d("BarService", "Bar is ready on screen:", screenName) - barReadyChanged(screenName) + readyBars[screenName] = true; + Logger.d("BarService", "Bar is ready on screen:", screenName); + barReadyChanged(screenName); } } // Function for the Dock to check if the bar is ready function isBarReady(screenName) { - return readyBars[screenName] || false + return readyBars[screenName] || false; } // Register a widget instance function registerWidget(screenName, section, widgetId, index, instance) { - const key = [screenName, section, widgetId, index].join("|") + const key = [screenName, section, widgetId, index].join("|"); widgetInstances[key] = { "key": key, "screenName": screenName, @@ -73,20 +73,20 @@ Singleton { "widgetId": widgetId, "index": index, "instance": instance - } + }; - timerCheckVisualizer.restart() + timerCheckVisualizer.restart(); - Logger.d("BarService", "Registered widget:", key) - root.activeWidgetsChanged() + Logger.d("BarService", "Registered widget:", key); + root.activeWidgetsChanged(); } // Unregister a widget instance function unregisterWidget(screenName, section, widgetId, index) { - const key = [screenName, section, widgetId, index].join("|") - delete widgetInstances[key] - Logger.d("BarService", "Unregistered widget:", key) - root.activeWidgetsChanged() + const key = [screenName, section, widgetId, index].join("|"); + delete widgetInstances[key]; + Logger.d("BarService", "Unregistered widget:", key); + root.activeWidgetsChanged(); } // Lookup a specific widget instance (returns the actual QML instance) @@ -94,12 +94,12 @@ Singleton { // If looking for a specific instance if (screenName && section !== null) { for (var key in widgetInstances) { - var widget = widgetInstances[key] + var widget = widgetInstances[key]; if (widget.widgetId === widgetId && widget.screenName === screenName && widget.section === section) { if (index === null) { - return widget.instance + return widget.instance; } else if (widget.index == index) { - return widget.instance + return widget.instance; } } } @@ -107,83 +107,83 @@ Singleton { // Return first match if no specific screen/section specified for (var key in widgetInstances) { - var widget = widgetInstances[key] + var widget = widgetInstances[key]; if (widget.widgetId === widgetId) { if (!screenName || widget.screenName === screenName) { if (section === null || widget.section === section) { - return widget.instance + return widget.instance; } } } } - return undefined + return undefined; } // Get all instances of a widget type function getAllWidgetInstances(widgetId = null, screenName = null, section = null) { - var instances = [] + var instances = []; for (var key in widgetInstances) { - var widget = widgetInstances[key] + var widget = widgetInstances[key]; - var matches = true + var matches = true; if (widgetId && widget.widgetId !== widgetId) - matches = false + matches = false; if (screenName && widget.screenName !== screenName) - matches = false + matches = false; if (section !== null && widget.section !== section) - matches = false + matches = false; if (matches) { - instances.push(widget.instance) + instances.push(widget.instance); } } - return instances + return instances; } // Get widget with full metadata function getWidgetWithMetadata(widgetId, screenName = null, section = null) { for (var key in widgetInstances) { - var widget = widgetInstances[key] + var widget = widgetInstances[key]; if (widget.widgetId === widgetId) { if (!screenName || widget.screenName === screenName) { if (section === null || widget.section === section) { - return widget + return widget; } } } } - return undefined + return undefined; } // Get all widgets in a specific section function getWidgetsBySection(section, screenName = null) { - var widgets = [] + var widgets = []; for (var key in widgetInstances) { - var widget = widgetInstances[key] + var widget = widgetInstances[key]; if (widget.section === section) { if (!screenName || widget.screenName === screenName) { - widgets.push(widget.instance) + widgets.push(widget.instance); } } } // Sort by index to maintain order widgets.sort(function (a, b) { - var aWidget = getWidgetWithMetadata(a.widgetId, a.screen?.name, a.section) - var bWidget = getWidgetWithMetadata(b.widgetId, b.screen?.name, b.section) - return (aWidget?.index || 0) - (bWidget?.index || 0) - }) + var aWidget = getWidgetWithMetadata(a.widgetId, a.screen?.name, a.section); + var bWidget = getWidgetWithMetadata(b.widgetId, b.screen?.name, b.section); + return (aWidget?.index || 0) - (bWidget?.index || 0); + }); - return widgets + return widgets; } // Get all registered widgets (for debugging) function getAllRegisteredWidgets() { - var result = [] + var result = []; for (var key in widgetInstances) { result.push({ "key": key, @@ -191,57 +191,57 @@ Singleton { "section": widgetInstances[key].section, "screenName": widgetInstances[key].screenName, "index": widgetInstances[key].index - }) + }); } - return result + return result; } // Check if a widget type exists in a section function hasWidget(widgetId, section = null, screenName = null) { for (var key in widgetInstances) { - var widget = widgetInstances[key] + var widget = widgetInstances[key]; if (widget.widgetId === widgetId) { if (section === null || widget.section === section) { if (!screenName || widget.screenName === screenName) { - return true + return true; } } } } - return false + return false; } // Get pill direction for a widget instance function getPillDirection(widgetInstance) { try { if (widgetInstance.section === "left") { - return true + return true; } else if (widgetInstance.section === "right") { - return false + return false; } else { // middle section if (widgetInstance.sectionWidgetIndex < widgetInstance.sectionWidgetsCount / 2) { - return false + return false; } else { - return true + return true; } } } catch (e) { - Logger.e(e) + Logger.e(e); } - return false + return false; } function getTooltipDirection() { switch (Settings.data.bar.position) { case "right": - return "left" + return "left"; case "left": - return "right" + return "right"; case "bottom": - return "top" + return "top"; default: - return "bottom" + return "bottom"; } } } diff --git a/Services/UI/BarWidgetRegistry.qml b/Services/UI/BarWidgetRegistry.qml index 1fa211ca..a7691e68 100644 --- a/Services/UI/BarWidgetRegistry.qml +++ b/Services/UI/BarWidgetRegistry.qml @@ -306,27 +306,27 @@ Singleton { } function init() { - Logger.i("BarWidgetRegistry", "Service started") + Logger.i("BarWidgetRegistry", "Service started"); } // ------------------------------ // Helper function to get widget component by name function getWidget(id) { - return widgets[id] || null + return widgets[id] || null; } // Helper function to check if widget exists function hasWidget(id) { - return id in widgets + return id in widgets; } // Get list of available widget id function getAvailableWidgets() { - return Object.keys(widgets) + return Object.keys(widgets); } // Helper function to check if widget has user settings function widgetHasUserSettings(id) { - return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true) + return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true); } } diff --git a/Services/UI/ControlCenterWidgetRegistry.qml b/Services/UI/ControlCenterWidgetRegistry.qml index b5da5473..23ef7370 100644 --- a/Services/UI/ControlCenterWidgetRegistry.qml +++ b/Services/UI/ControlCenterWidgetRegistry.qml @@ -64,27 +64,27 @@ Singleton { } function init() { - Logger.i("ControlCenterWidgetRegistry", "Service started") + Logger.i("ControlCenterWidgetRegistry", "Service started"); } // ------------------------------ // Helper function to get widget component by name function getWidget(id) { - return widgets[id] || null + return widgets[id] || null; } // Helper function to check if widget exists function hasWidget(id) { - return id in widgets + return id in widgets; } // Get list of available widget id function getAvailableWidgets() { - return Object.keys(widgets) + return Object.keys(widgets); } // Helper function to check if widget has user settings function widgetHasUserSettings(id) { - return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true) + return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true); } } diff --git a/Services/UI/PanelService.qml b/Services/UI/PanelService.qml index 51ae69c0..675508d0 100644 --- a/Services/UI/PanelService.qml +++ b/Services/UI/PanelService.qml @@ -22,73 +22,73 @@ Singleton { // Register this panel (called after panel is loaded) function registerPanel(panel) { - registeredPanels[panel.objectName] = panel - Logger.d("PanelService", "Registered panel:", panel.objectName) + registeredPanels[panel.objectName] = panel; + Logger.d("PanelService", "Registered panel:", panel.objectName); } // Register tray menu window for a screen function registerTrayMenuWindow(screen, window) { if (!screen || !window) - return - var key = screen.name - trayMenuWindows[key] = window - Logger.d("PanelService", "Registered tray menu window for screen:", key) - trayMenuWindowRegistered(screen) + return; + var key = screen.name; + trayMenuWindows[key] = window; + Logger.d("PanelService", "Registered tray menu window for screen:", key); + trayMenuWindowRegistered(screen); } // Get tray menu window for a screen function getTrayMenuWindow(screen) { if (!screen) - return null - return trayMenuWindows[screen.name] || null + return null; + return trayMenuWindows[screen.name] || null; } // Returns a panel (loads it on-demand if not yet loaded) function getPanel(name, screen) { if (!screen) { - Logger.d("PanelService", "missing screen for getPanel:", name) + Logger.d("PanelService", "missing screen for getPanel:", name); // If no screen specified, return the first matching panel for (var key in registeredPanels) { if (key.startsWith(name + "-")) { - return registeredPanels[key] + return registeredPanels[key]; } } - return null + return null; } - var panelKey = `${name}-${screen.name}` + var panelKey = `${name}-${screen.name}`; // Check if panel is already loaded if (registeredPanels[panelKey]) { - return registeredPanels[panelKey] + return registeredPanels[panelKey]; } - Logger.w("PanelService", "Panel not found:", panelKey) - return null + Logger.w("PanelService", "Panel not found:", panelKey); + return null; } // Check if a panel exists function hasPanel(name) { - return name in registeredPanels + return name in registeredPanels; } // Helper to keep only one panel open at any time function willOpenPanel(panel) { if (openedPanel && openedPanel !== panel) { - openedPanel.close() + openedPanel.close(); } - openedPanel = panel + openedPanel = panel; // emit signal - willOpen() + willOpen(); } function closedPanel(panel) { if (openedPanel && openedPanel === panel) { - openedPanel = null + openedPanel = null; } // emit signal - didClose() + didClose(); } } diff --git a/Services/UI/SystemTrayService.qml b/Services/UI/SystemTrayService.qml deleted file mode 100644 index 4f2e74ce..00000000 --- a/Services/UI/SystemTrayService.qml +++ /dev/null @@ -1,40 +0,0 @@ -pragma Singleton - -import QtQuick -import Quickshell -import Quickshell.Services.SystemTray -import qs.Commons - - -/** - * SystemTrayService - * This service ensures that Quickshell's SystemTray service is initialized - * early in the shell startup to avoid programs that should stay in tray, not having access to one (let's hope this works). - */ -Singleton { - id: root - - property bool initialized: false - - Component.onCompleted: { - if (SystemTray && SystemTray.items) { - Logger.i("SystemTrayService", "SystemTray service initialized") - initialized = true - - // Monitor for tray items to confirm it's working - if (SystemTray.items.valuesChanged) { - Logger.d("SystemTrayService", "SystemTray is ready and monitoring for items") - } - } else { - Logger.w("SystemTrayService", "SystemTray service not available") - } - } - - function init() { - // Explicit initialization function - if (!initialized && SystemTray && SystemTray.items) { - Logger.i("SystemTrayService", "SystemTray service initialized via init()") - initialized = true - } - } -} diff --git a/Services/UI/ToastService.qml b/Services/UI/ToastService.qml index 5a5a0929..ee7647b8 100644 --- a/Services/UI/ToastService.qml +++ b/Services/UI/ToastService.qml @@ -11,14 +11,14 @@ Singleton { // Convenience methods function showNotice(message, description = "", icon = "", duration = 3000) { - notify(message, description, icon, "notice", duration) + notify(message, description, icon, "notice", duration); } function showWarning(message, description = "", duration = 4000) { - notify(message, description, "", "warning", duration) + notify(message, description, "", "warning", duration); } function showError(message, description = "", duration = 6000) { - notify(message, description, "", "error", duration) + notify(message, description, "", "error", duration); } } diff --git a/Services/UI/TooltipService.qml b/Services/UI/TooltipService.qml index 4e2b98b4..a1ab7c61 100644 --- a/Services/UI/TooltipService.qml +++ b/Services/UI/TooltipService.qml @@ -17,41 +17,41 @@ Singleton { function show(screen, target, text, direction, delay, fontFamily) { if (!Settings.data.ui.tooltipsEnabled) { - return + return; } // Don't create if no text if (!screen || !target || !text) { - Logger.i("Tooltip", "No target or text") - return + Logger.i("Tooltip", "No target or text"); + return; } // If we have a pending tooltip for a different target, cancel it if (pendingTooltip && pendingTooltip.targetItem !== target) { - pendingTooltip.hideImmediately() - pendingTooltip.destroy() - pendingTooltip = null + pendingTooltip.hideImmediately(); + pendingTooltip.destroy(); + pendingTooltip = null; } // If we have an active tooltip for a different target, hide it if (activeTooltip && activeTooltip.targetItem !== target) { - activeTooltip.hideImmediately() + activeTooltip.hideImmediately(); // Don't destroy immediately - let it clean itself up - activeTooltip = null + activeTooltip = null; } // If we already have a tooltip for this target, just update it if (activeTooltip && activeTooltip.targetItem === target) { - activeTooltip.updateText(text) - return activeTooltip + activeTooltip.updateText(text); + return activeTooltip; } // Create new tooltip instance - const newTooltip = tooltipComponent.createObject(null) + const newTooltip = tooltipComponent.createObject(null); if (newTooltip) { // Track as pending until it's visible - pendingTooltip = newTooltip + pendingTooltip = newTooltip; // Connect cleanup when tooltip hides newTooltip.visibleChanged.connect(() => { @@ -60,59 +60,59 @@ Singleton { Qt.callLater(() => { if (newTooltip && !newTooltip.visible) { if (activeTooltip === newTooltip) { - activeTooltip = null + activeTooltip = null; } if (pendingTooltip === newTooltip) { - pendingTooltip = null + pendingTooltip = null; } - newTooltip.destroy() + newTooltip.destroy(); } - }) + }); } else { // Tooltip is now visible, move from pending to active if (pendingTooltip === newTooltip) { - activeTooltip = newTooltip - pendingTooltip = null + activeTooltip = newTooltip; + pendingTooltip = null; } } - }) + }); // Show the tooltip - newTooltip.show(screen, target, text, direction || "auto", delay || Style.tooltipDelay, fontFamily) + newTooltip.show(screen, target, text, direction || "auto", delay || Style.tooltipDelay, fontFamily); - return newTooltip + return newTooltip; } else { - Logger.e("Tooltip", "Failed to create tooltip instance") + Logger.e("Tooltip", "Failed to create tooltip instance"); } - return null + return null; } function hide() { if (pendingTooltip) { - pendingTooltip.hide() + pendingTooltip.hide(); } if (activeTooltip) { - activeTooltip.hide() + activeTooltip.hide(); } } function hideImmediately() { if (pendingTooltip) { - pendingTooltip.hideImmediately() - pendingTooltip.destroy() - pendingTooltip = null + pendingTooltip.hideImmediately(); + pendingTooltip.destroy(); + pendingTooltip = null; } if (activeTooltip) { - activeTooltip.hideImmediately() - activeTooltip.destroy() - activeTooltip = null + activeTooltip.hideImmediately(); + activeTooltip.destroy(); + activeTooltip = null; } } function updateText(newText) { if (activeTooltip) { - activeTooltip.updateText(newText) + activeTooltip.updateText(newText); } } } diff --git a/Services/UI/WallhavenService.qml b/Services/UI/WallhavenService.qml index e5e4c209..95863369 100644 --- a/Services/UI/WallhavenService.qml +++ b/Services/UI/WallhavenService.qml @@ -40,170 +40,170 @@ Singleton { // ------------------------------------------------- function search(query, page) { if (fetching) { - return + return; } // Reset initial search flag once we start a search if (initialSearchScheduled) { - initialSearchScheduled = false + initialSearchScheduled = false; } - fetching = true - lastError = "" - currentQuery = query || "" - currentPage = page || 1 + fetching = true; + lastError = ""; + currentQuery = query || ""; + currentPage = page || 1; - var url = apiBaseUrl + "/search" - var params = [] + var url = apiBaseUrl + "/search"; + var params = []; if (currentQuery) { - params.push("q=" + encodeURIComponent(currentQuery)) + params.push("q=" + encodeURIComponent(currentQuery)); } - params.push("categories=" + categories) - params.push("purity=" + purity) - params.push("sorting=" + sorting) - params.push("order=" + order) + params.push("categories=" + categories); + params.push("purity=" + purity); + params.push("sorting=" + sorting); + params.push("order=" + order); if (sorting === "toplist") { - params.push("topRange=" + topRange) + params.push("topRange=" + topRange); } if (sorting === "random" && seed) { - params.push("seed=" + seed) + params.push("seed=" + seed); } if (minResolution) { - params.push("atleast=" + minResolution) + params.push("atleast=" + minResolution); } if (resolutions) { - params.push("resolutions=" + resolutions) + params.push("resolutions=" + resolutions); } if (ratios) { - params.push("ratios=" + ratios) + params.push("ratios=" + ratios); } if (colors) { - params.push("colors=" + colors) + params.push("colors=" + colors); } - params.push("page=" + currentPage) + params.push("page=" + currentPage); - url += "?" + params.join("&") + url += "?" + params.join("&"); - Logger.d("Wallhaven", "Searching:", url) + Logger.d("Wallhaven", "Searching:", url); - var xhr = new XMLHttpRequest() + var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE) { - fetching = false + fetching = false; if (xhr.status === 200) { try { - var response = JSON.parse(xhr.responseText) + var response = JSON.parse(xhr.responseText); if (response.data && Array.isArray(response.data)) { - currentResults = response.data - currentMeta = response.meta || {} - lastPage = currentMeta.last_page || 1 + currentResults = response.data; + currentMeta = response.meta || {}; + lastPage = currentMeta.last_page || 1; // Store seed for random sorting if (currentMeta.seed) { - seed = currentMeta.seed + seed = currentMeta.seed; } - Logger.d("Wallhaven", "Search completed:", currentResults.length, "results, page", currentPage, "of", lastPage) - searchCompleted(currentResults, currentMeta) + Logger.d("Wallhaven", "Search completed:", currentResults.length, "results, page", currentPage, "of", lastPage); + searchCompleted(currentResults, currentMeta); } else { - var errorMsg = "Invalid API response" - lastError = errorMsg - Logger.e("Wallhaven", errorMsg) - searchFailed(errorMsg) + var errorMsg = "Invalid API response"; + lastError = errorMsg; + Logger.e("Wallhaven", errorMsg); + searchFailed(errorMsg); } } catch (e) { - var errorMsg = "Failed to parse API response: " + e.toString() - lastError = errorMsg - Logger.e("Wallhaven", errorMsg) - searchFailed(errorMsg) + var errorMsg = "Failed to parse API response: " + e.toString(); + lastError = errorMsg; + Logger.e("Wallhaven", errorMsg); + searchFailed(errorMsg); } } else if (xhr.status === 429) { - var errorMsg = "Rate limit exceeded (45 requests/minute)" - lastError = errorMsg - Logger.w("Wallhaven", errorMsg) - searchFailed(errorMsg) + var errorMsg = "Rate limit exceeded (45 requests/minute)"; + lastError = errorMsg; + Logger.w("Wallhaven", errorMsg); + searchFailed(errorMsg); } else { - var errorMsg = "API error: " + xhr.status - lastError = errorMsg - Logger.e("Wallhaven", "Search failed:", errorMsg) - searchFailed(errorMsg) + var errorMsg = "API error: " + xhr.status; + lastError = errorMsg; + Logger.e("Wallhaven", "Search failed:", errorMsg); + searchFailed(errorMsg); } } - } + }; - xhr.open("GET", url) - xhr.send() + xhr.open("GET", url); + xhr.send(); } // ------------------------------------------------- function getWallpaperUrl(wallpaper) { // Use the 'path' field which contains the full resolution image URL if (wallpaper.path) { - return wallpaper.path + return wallpaper.path; } // Fallback to constructing URL from ID if (wallpaper.id) { - var idPrefix = wallpaper.id.substring(0, 2) - return "https://w.wallhaven.cc/full/" + idPrefix + "/wallhaven-" + wallpaper.id + ".jpg" + var idPrefix = wallpaper.id.substring(0, 2); + return "https://w.wallhaven.cc/full/" + idPrefix + "/wallhaven-" + wallpaper.id + ".jpg"; } - return "" + return ""; } // ------------------------------------------------- function getThumbnailUrl(wallpaper, size) { // size: "small", "large", "original" if (wallpaper.thumbs && wallpaper.thumbs[size]) { - return wallpaper.thumbs[size] + return wallpaper.thumbs[size]; } // Fallback if (wallpaper.id) { - var idPrefix = wallpaper.id.substring(0, 2) + var idPrefix = wallpaper.id.substring(0, 2); var sizeMap = { "small": "small", "large": "lg", "original": "orig" - } - var sizePath = sizeMap[size] || "lg" - return "https://th.wallhaven.cc/" + sizePath + "/" + idPrefix + "/" + wallpaper.id + ".jpg" + }; + var sizePath = sizeMap[size] || "lg"; + return "https://th.wallhaven.cc/" + sizePath + "/" + idPrefix + "/" + wallpaper.id + ".jpg"; } - return "" + return ""; } // ------------------------------------------------- function downloadWallpaper(wallpaper, callback) { - var url = getWallpaperUrl(wallpaper) + var url = getWallpaperUrl(wallpaper); if (!url) { - Logger.e("Wallhaven", "No URL available for wallpaper", wallpaper.id) + Logger.e("Wallhaven", "No URL available for wallpaper", wallpaper.id); if (callback) - callback(false, "") - return + callback(false, ""); + return; } - var wallpaperId = wallpaper.id + var wallpaperId = wallpaper.id; // Get the user's wallpaper directory - var wallpaperDir = Settings.preprocessPath(Settings.data.wallpaper.directory) + var wallpaperDir = Settings.preprocessPath(Settings.data.wallpaper.directory); if (!wallpaperDir || wallpaperDir === "") { - wallpaperDir = Settings.defaultWallpapersDirectory + wallpaperDir = Settings.defaultWallpapersDirectory; } // Ensure directory ends with / if (!wallpaperDir.endsWith("/")) { - wallpaperDir += "/" + wallpaperDir += "/"; } - var localPath = wallpaperDir + "wallhaven_" + wallpaperId + ".jpg" + var localPath = wallpaperDir + "wallhaven_" + wallpaperId + ".jpg"; - Logger.d("Wallhaven", "Downloading wallpaper", wallpaperId, "to", localPath) + Logger.d("Wallhaven", "Downloading wallpaper", wallpaperId, "to", localPath); // Use curl or wget to download the file, ensuring directory exists first var downloadProcess = Qt.createQmlObject(` @@ -213,47 +213,47 @@ Singleton { id: downloadProcess command: ["sh", "-c", "mkdir -p '` + wallpaperDir + `' && (curl -L -s -o '` + localPath + `' '` + url + `' || wget -q -O '` + localPath + `' '` + url + `')"] } - `, root, "DownloadProcess_" + wallpaperId) + `, root, "DownloadProcess_" + wallpaperId); downloadProcess.exited.connect(function (exitCode) { if (exitCode === 0) { - Logger.i("Wallhaven", "Wallpaper downloaded:", localPath) - wallpaperDownloaded(wallpaperId, localPath) + Logger.i("Wallhaven", "Wallpaper downloaded:", localPath); + wallpaperDownloaded(wallpaperId, localPath); if (callback) - callback(true, localPath) + callback(true, localPath); } else { - Logger.e("Wallhaven", "Failed to download wallpaper, exit code:", exitCode) + Logger.e("Wallhaven", "Failed to download wallpaper, exit code:", exitCode); if (callback) - callback(false, "") + callback(false, ""); } - downloadProcess.destroy() - }) + downloadProcess.destroy(); + }); - downloadProcess.running = true + downloadProcess.running = true; } // ------------------------------------------------- function reset() { - currentResults = [] - currentMeta = {} - currentQuery = "" - currentPage = 1 - lastPage = 1 - seed = "" - lastError = "" + currentResults = []; + currentMeta = {}; + currentQuery = ""; + currentPage = 1; + lastPage = 1; + seed = ""; + lastError = ""; } // ------------------------------------------------- function nextPage() { if (currentPage < lastPage && !fetching) { - search(currentQuery, currentPage + 1) + search(currentQuery, currentPage + 1); } } // ------------------------------------------------- function previousPage() { if (currentPage > 1 && !fetching) { - search(currentQuery, currentPage - 1) + search(currentQuery, currentPage - 1); } } } diff --git a/Services/UI/WallpaperService.qml b/Services/UI/WallpaperService.qml index a01c2653..b138e398 100644 --- a/Services/UI/WallpaperService.qml +++ b/Services/UI/WallpaperService.qml @@ -1,7 +1,7 @@ pragma Singleton +import Qt.labs.folderlistmodel import QtQuick -import Qt.labs.folderlistmodel import Quickshell import Quickshell.Io import qs.Commons @@ -40,69 +40,69 @@ Singleton { Connections { target: Settings.data.wallpaper function onDirectoryChanged() { - root.refreshWallpapersList() + root.refreshWallpapersList(); // Emit directory change signals for monitors using the default directory if (!Settings.data.wallpaper.enableMultiMonitorDirectories) { // All monitors use the main directory for (var i = 0; i < Quickshell.screens.length; i++) { - root.wallpaperDirectoryChanged(Quickshell.screens[i].name, root.defaultDirectory) + root.wallpaperDirectoryChanged(Quickshell.screens[i].name, root.defaultDirectory); } } else { // Only monitors without custom directories are affected for (var i = 0; i < Quickshell.screens.length; i++) { - var screenName = Quickshell.screens[i].name - var monitor = root.getMonitorConfig(screenName) + var screenName = Quickshell.screens[i].name; + var monitor = root.getMonitorConfig(screenName); if (!monitor || !monitor.directory) { - root.wallpaperDirectoryChanged(screenName, root.defaultDirectory) + root.wallpaperDirectoryChanged(screenName, root.defaultDirectory); } } } } function onEnableMultiMonitorDirectoriesChanged() { - root.refreshWallpapersList() + root.refreshWallpapersList(); // Notify all monitors about potential directory changes for (var i = 0; i < Quickshell.screens.length; i++) { - var screenName = Quickshell.screens[i].name - root.wallpaperDirectoryChanged(screenName, root.getMonitorDirectory(screenName)) + var screenName = Quickshell.screens[i].name; + root.wallpaperDirectoryChanged(screenName, root.getMonitorDirectory(screenName)); } } function onRandomEnabledChanged() { - root.toggleRandomWallpaper() + root.toggleRandomWallpaper(); } function onRandomIntervalSecChanged() { - root.restartRandomWallpaperTimer() + root.restartRandomWallpaperTimer(); } function onRecursiveSearchChanged() { - root.refreshWallpapersList() + root.refreshWallpapersList(); } } // ------------------------------------------------- function init() { - Logger.i("Wallpaper", "Service started") + Logger.i("Wallpaper", "Service started"); - translateModels() + translateModels(); // Rebuild cache from settings - currentWallpapers = ({}) - var monitors = Settings.data.wallpaper.monitors || [] + currentWallpapers = ({}); + var monitors = Settings.data.wallpaper.monitors || []; for (var i = 0; i < monitors.length; i++) { if (monitors[i].name && monitors[i].wallpaper) { - currentWallpapers[monitors[i].name] = monitors[i].wallpaper + currentWallpapers[monitors[i].name] = monitors[i].wallpaper; } } - isInitialized = true - Logger.d("Wallpaper", "Triggering initial wallpaper scan") - Qt.callLater(refreshWallpapersList) + isInitialized = true; + Logger.d("Wallpaper", "Triggering initial wallpaper scan"); + Qt.callLater(refreshWallpapersList); } // ------------------------------------------------- function translateModels() { // Wait for i18n to be ready by retrying every time if (!I18n.isLoaded) { - Qt.callLater(translateModels) - return + Qt.callLater(translateModels); + return; } // Populate fillModeModel with translated names @@ -110,70 +110,70 @@ Singleton { "key": "center", "name": I18n.tr("wallpaper.fill-modes.center"), "uniform": 0.0 - }) + }); fillModeModel.append({ "key": "crop", "name": I18n.tr("wallpaper.fill-modes.crop"), "uniform": 1.0 - }) + }); fillModeModel.append({ "key": "fit", "name": I18n.tr("wallpaper.fill-modes.fit"), "uniform": 2.0 - }) + }); fillModeModel.append({ "key": "stretch", "name": I18n.tr("wallpaper.fill-modes.stretch"), "uniform": 3.0 - }) + }); // Populate transitionsModel with translated names transitionsModel.append({ "key": "none", "name": I18n.tr("wallpaper.transitions.none") - }) + }); transitionsModel.append({ "key": "random", "name": I18n.tr("wallpaper.transitions.random") - }) + }); transitionsModel.append({ "key": "fade", "name": I18n.tr("wallpaper.transitions.fade") - }) + }); transitionsModel.append({ "key": "disc", "name": I18n.tr("wallpaper.transitions.disc") - }) + }); transitionsModel.append({ "key": "stripes", "name": I18n.tr("wallpaper.transitions.stripes") - }) + }); transitionsModel.append({ "key": "wipe", "name": I18n.tr("wallpaper.transitions.wipe") - }) + }); } // ------------------------------------------------------------------- function getFillModeUniform() { for (var i = 0; i < fillModeModel.count; i++) { - const mode = fillModeModel.get(i) + const mode = fillModeModel.get(i); if (mode.key === Settings.data.wallpaper.fillMode) { - return mode.uniform + return mode.uniform; } } // Fallback to crop - return 1.0 + return 1.0; } // ------------------------------------------------------------------- // Get specific monitor wallpaper data function getMonitorConfig(screenName) { - var monitors = Settings.data.wallpaper.monitors + var monitors = Settings.data.wallpaper.monitors; if (monitors !== undefined) { for (var i = 0; i < monitors.length; i++) { if (monitors[i].name !== undefined && monitors[i].name === screenName) { - return monitors[i] + return monitors[i]; } } } @@ -183,64 +183,64 @@ Singleton { // Get specific monitor directory function getMonitorDirectory(screenName) { if (!Settings.data.wallpaper.enableMultiMonitorDirectories) { - return root.defaultDirectory + return root.defaultDirectory; } - var monitor = getMonitorConfig(screenName) + var monitor = getMonitorConfig(screenName); if (monitor !== undefined && monitor.directory !== undefined) { - return Settings.preprocessPath(monitor.directory) + return Settings.preprocessPath(monitor.directory); } // Fall back to the main/single directory - return root.defaultDirectory + return root.defaultDirectory; } // ------------------------------------------------------------------- // Set specific monitor directory function setMonitorDirectory(screenName, directory) { - var monitors = Settings.data.wallpaper.monitors || [] - var found = false + var monitors = Settings.data.wallpaper.monitors || []; + var found = false; // Create a new array with updated values var newMonitors = monitors.map(function (monitor) { if (monitor.name === screenName) { - found = true + found = true; return { "name": screenName, "directory": directory, "wallpaper": monitor.wallpaper || "" - } + }; } - return monitor - }) + return monitor; + }); if (!found) { newMonitors.push({ "name": screenName, "directory": directory, "wallpaper": "" - }) + }); } // Update Settings with new array to ensure proper persistence - Settings.data.wallpaper.monitors = newMonitors.slice() - root.wallpaperDirectoryChanged(screenName, Settings.preprocessPath(directory)) + Settings.data.wallpaper.monitors = newMonitors.slice(); + root.wallpaperDirectoryChanged(screenName, Settings.preprocessPath(directory)); } // ------------------------------------------------------------------- // Get specific monitor wallpaper - now from cache function getWallpaper(screenName) { - return currentWallpapers[screenName] || Settings.data.wallpaper.defaultWallpaper + return currentWallpapers[screenName] || Settings.data.wallpaper.defaultWallpaper; } // ------------------------------------------------------------------- function changeWallpaper(path, screenName) { if (screenName !== undefined) { - _setWallpaper(screenName, path) + _setWallpaper(screenName, path); } else { // If no screenName specified change for all screens for (var i = 0; i < Quickshell.screens.length; i++) { - _setWallpaper(Quickshell.screens[i].name, path) + _setWallpaper(Quickshell.screens[i].name, path); } } } @@ -248,144 +248,144 @@ Singleton { // ------------------------------------------------------------------- function _setWallpaper(screenName, path) { if (path === "" || path === undefined) { - return + return; } if (screenName === undefined) { - Logger.w("Wallpaper", "setWallpaper", "no screen specified") - return + Logger.w("Wallpaper", "setWallpaper", "no screen specified"); + return; } //Logger.i("Wallpaper", "setWallpaper on", screenName, ": ", path) // Check if wallpaper actually changed - var oldPath = currentWallpapers[screenName] || "" - var wallpaperChanged = (oldPath !== path) + var oldPath = currentWallpapers[screenName] || ""; + var wallpaperChanged = (oldPath !== path); if (!wallpaperChanged) { // No change needed - return + return; } // Update cache directly - currentWallpapers[screenName] = path + currentWallpapers[screenName] = path; // Update Settings - still need immutable update for Settings persistence // The slice() ensures Settings detects the change and saves properly - var monitors = Settings.data.wallpaper.monitors || [] - var found = false + var monitors = Settings.data.wallpaper.monitors || []; + var found = false; var newMonitors = monitors.map(function (monitor) { if (monitor.name === screenName) { - found = true + found = true; return { "name": screenName, "directory": Settings.preprocessPath(monitor.directory) || getMonitorDirectory(screenName), "wallpaper": path - } + }; } - return monitor - }) + return monitor; + }); if (!found) { newMonitors.push({ "name": screenName, "directory": getMonitorDirectory(screenName), "wallpaper": path - }) + }); } - Settings.data.wallpaper.monitors = newMonitors.slice() + Settings.data.wallpaper.monitors = newMonitors.slice(); // Emit signal for this specific wallpaper change - root.wallpaperChanged(screenName, path) + root.wallpaperChanged(screenName, path); // Restart the random wallpaper timer if (randomWallpaperTimer.running) { - randomWallpaperTimer.restart() + randomWallpaperTimer.restart(); } } // ------------------------------------------------------------------- function setRandomWallpaper() { - Logger.d("Wallpaper", "setRandomWallpaper") + Logger.d("Wallpaper", "setRandomWallpaper"); if (Settings.data.wallpaper.enableMultiMonitorDirectories) { // Pick a random wallpaper per screen for (var i = 0; i < Quickshell.screens.length; i++) { - var screenName = Quickshell.screens[i].name - var wallpaperList = getWallpapersList(screenName) + var screenName = Quickshell.screens[i].name; + var wallpaperList = getWallpapersList(screenName); if (wallpaperList.length > 0) { - var randomIndex = Math.floor(Math.random() * wallpaperList.length) - var randomPath = wallpaperList[randomIndex] - changeWallpaper(randomPath, screenName) + var randomIndex = Math.floor(Math.random() * wallpaperList.length); + var randomPath = wallpaperList[randomIndex]; + changeWallpaper(randomPath, screenName); } } } else { // Pick a random wallpaper common to all screens // We can use any screenName here, so we just pick the primary one. - var wallpaperList = getWallpapersList(Screen.name) + var wallpaperList = getWallpapersList(Screen.name); if (wallpaperList.length > 0) { - var randomIndex = Math.floor(Math.random() * wallpaperList.length) - var randomPath = wallpaperList[randomIndex] - changeWallpaper(randomPath, undefined) + var randomIndex = Math.floor(Math.random() * wallpaperList.length); + var randomPath = wallpaperList[randomIndex]; + changeWallpaper(randomPath, undefined); } } } // ------------------------------------------------------------------- function toggleRandomWallpaper() { - Logger.d("Wallpaper", "toggleRandomWallpaper") + Logger.d("Wallpaper", "toggleRandomWallpaper"); if (Settings.data.wallpaper.randomEnabled) { - restartRandomWallpaperTimer() - setRandomWallpaper() + restartRandomWallpaperTimer(); + setRandomWallpaper(); } } // ------------------------------------------------------------------- function restartRandomWallpaperTimer() { if (Settings.data.wallpaper.isRandom) { - randomWallpaperTimer.restart() + randomWallpaperTimer.restart(); } } // ------------------------------------------------------------------- function getWallpapersList(screenName) { if (screenName != undefined && wallpaperLists[screenName] != undefined) { - return wallpaperLists[screenName] + return wallpaperLists[screenName]; } - return [] + return []; } // ------------------------------------------------------------------- function refreshWallpapersList() { - Logger.d("Wallpaper", "refreshWallpapersList", "recursive:", Settings.data.wallpaper.recursiveSearch) - scanningCount = 0 + Logger.d("Wallpaper", "refreshWallpapersList", "recursive:", Settings.data.wallpaper.recursiveSearch); + scanningCount = 0; if (Settings.data.wallpaper.recursiveSearch) { // Use Process-based recursive search for all screens for (var i = 0; i < Quickshell.screens.length; i++) { - var screenName = Quickshell.screens[i].name - var directory = getMonitorDirectory(screenName) - scanDirectoryRecursive(screenName, directory) + var screenName = Quickshell.screens[i].name; + var directory = getMonitorDirectory(screenName); + scanDirectoryRecursive(screenName, directory); } } else { // Use FolderListModel (non-recursive) // Force refresh by toggling each scanner's currentDirectory for (var i = 0; i < wallpaperScanners.count; i++) { - var scanner = wallpaperScanners.objectAt(i) + var scanner = wallpaperScanners.objectAt(i); if (scanner) { // Capture scanner in closure (function (s) { - var directory = root.getMonitorDirectory(s.screenName) + var directory = root.getMonitorDirectory(s.screenName); // Trigger a change by setting to /tmp (always exists) then back to the actual directory // Note: This causes harmless Qt warnings (QTBUG-52262) but is necessary to force FolderListModel to re-scan - s.currentDirectory = "/tmp" + s.currentDirectory = "/tmp"; Qt.callLater(function () { - s.currentDirectory = directory - }) - })(scanner) + s.currentDirectory = directory; + }); + })(scanner); } } } @@ -397,26 +397,26 @@ Singleton { // ------------------------------------------------------------------- function scanDirectoryRecursive(screenName, directory) { if (!directory || directory === "") { - Logger.w("Wallpaper", "Empty directory for", screenName) - wallpaperLists[screenName] = [] - wallpaperListChanged(screenName, 0) - return + Logger.w("Wallpaper", "Empty directory for", screenName); + wallpaperLists[screenName] = []; + wallpaperListChanged(screenName, 0); + return; } // Cancel any existing scan for this screen if (recursiveProcesses[screenName]) { - Logger.d("Wallpaper", "Cancelling existing scan for", screenName) - recursiveProcesses[screenName].running = false - recursiveProcesses[screenName].destroy() - delete recursiveProcesses[screenName] - scanningCount-- + Logger.d("Wallpaper", "Cancelling existing scan for", screenName); + recursiveProcesses[screenName].running = false; + recursiveProcesses[screenName].destroy(); + delete recursiveProcesses[screenName]; + scanningCount--; } - scanningCount++ - Logger.i("Wallpaper", "Starting recursive scan for", screenName, "in", directory) + scanningCount++; + Logger.i("Wallpaper", "Starting recursive scan for", screenName, "in", directory); // Create Process component inline - var processComponent = Qt.createComponent("", root) + var processComponent = Qt.createComponent("", root); var processString = ` import QtQuick import Quickshell.Io @@ -426,43 +426,43 @@ Singleton { stdout: StdioCollector {} stderr: StdioCollector {} } - ` + `; - var processObject = Qt.createQmlObject(processString, root, "RecursiveScan_" + screenName) + var processObject = Qt.createQmlObject(processString, root, "RecursiveScan_" + screenName); // Store reference to avoid garbage collection - recursiveProcesses[screenName] = processObject + recursiveProcesses[screenName] = processObject; var handler = function (exitCode) { - scanningCount-- - Logger.d("Wallpaper", "Process exited with code", exitCode, "for", screenName) + scanningCount--; + Logger.d("Wallpaper", "Process exited with code", exitCode, "for", screenName); if (exitCode === 0) { - var lines = processObject.stdout.text.split('\n') - var files = [] + var lines = processObject.stdout.text.split('\n'); + var files = []; for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim() + var line = lines[i].trim(); if (line !== '') { - files.push(line) + files.push(line); } } // Sort files for consistent ordering - files.sort() - wallpaperLists[screenName] = files - Logger.i("Wallpaper", "Recursive scan completed for", screenName, "found", files.length, "files") - wallpaperListChanged(screenName, files.length) + files.sort(); + wallpaperLists[screenName] = files; + Logger.i("Wallpaper", "Recursive scan completed for", screenName, "found", files.length, "files"); + wallpaperListChanged(screenName, files.length); } else { - Logger.w("Wallpaper", "Recursive scan failed for", screenName, "exit code:", exitCode, "(directory might not exist)") - wallpaperLists[screenName] = [] - wallpaperListChanged(screenName, 0) + Logger.w("Wallpaper", "Recursive scan failed for", screenName, "exit code:", exitCode, "(directory might not exist)"); + wallpaperLists[screenName] = []; + wallpaperListChanged(screenName, 0); } // Clean up - delete recursiveProcesses[screenName] - processObject.destroy() - } + delete recursiveProcesses[screenName]; + processObject.destroy(); + }; - processObject.exited.connect(handler) - Logger.d("Wallpaper", "Starting process for", screenName) - processObject.running = true + processObject.exited.connect(handler); + Logger.d("Wallpaper", "Starting process for", screenName); + processObject.running = true; } // ------------------------------------------------------------------- @@ -492,41 +492,41 @@ Singleton { // Watch for directory changes via property binding onCurrentDirectoryChanged: { - folder = "file://" + currentDirectory + folder = "file://" + currentDirectory; } Component.onCompleted: { // Connect to directory change signal root.wallpaperDirectoryChanged.connect(function (screen, directory) { if (screen === screenName) { - currentDirectory = directory + currentDirectory = directory; } - }) + }); } onStatusChanged: { if (status === FolderListModel.Null) { // Flush the list - root.wallpaperLists[screenName] = [] - root.wallpaperListChanged(screenName, 0) + root.wallpaperLists[screenName] = []; + root.wallpaperListChanged(screenName, 0); } else if (status === FolderListModel.Loading) { // Flush the list - root.wallpaperLists[screenName] = [] - scanningCount++ + root.wallpaperLists[screenName] = []; + scanningCount++; } else if (status === FolderListModel.Ready) { - var files = [] + var files = []; for (var i = 0; i < count; i++) { - var directory = root.getMonitorDirectory(screenName) - var filepath = directory + "/" + get(i, "fileName") - files.push(filepath) + var directory = root.getMonitorDirectory(screenName); + var filepath = directory + "/" + get(i, "fileName"); + files.push(filepath); } // Update the list - root.wallpaperLists[screenName] = files + root.wallpaperLists[screenName] = files; - scanningCount-- - Logger.d("Wallpaper", "List refreshed for", screenName, "count:", files.length) - root.wallpaperListChanged(screenName, files.length) + scanningCount--; + Logger.d("Wallpaper", "List refreshed for", screenName, "count:", files.length); + root.wallpaperListChanged(screenName, files.length); } } } diff --git a/Widgets/AudioSpectrum/NWaveSpectrum.qml b/Widgets/AudioSpectrum/NWaveSpectrum.qml index e2a78fe9..fff36e50 100644 --- a/Widgets/AudioSpectrum/NWaveSpectrum.qml +++ b/Widgets/AudioSpectrum/NWaveSpectrum.qml @@ -37,10 +37,10 @@ Item { // Clear canvas when not rendering onRenderingActiveChanged: { if (!renderingActive) { - var ctx = canvas.getContext("2d") + var ctx = canvas.getContext("2d"); if (ctx) - ctx.reset() - canvas.requestPaint() + ctx.reset(); + canvas.requestPaint(); } } @@ -52,96 +52,96 @@ Item { renderTarget: Canvas.FramebufferObject // Use FBO for better performance onPaint: { - var ctx = getContext("2d") - ctx.reset() + var ctx = getContext("2d"); + ctx.reset(); if (!values || !Array.isArray(values) || values.length === 0) { - return + return; } // Apply minimum signal if enabled var processedValues = values.map(function (v) { - return (root.showMinimumSignal && v === 0) ? root.minimumSignalValue : v - }) + return (root.showMinimumSignal && v === 0) ? root.minimumSignalValue : v; + }); // Create the mirrored values - const partToMirror = processedValues.slice(1).reverse() - const mirroredValues = partToMirror.concat(processedValues) + const partToMirror = processedValues.slice(1).reverse(); + const mirroredValues = partToMirror.concat(processedValues); if (mirroredValues.length < 2) { - return + return; } - ctx.fillStyle = root.fillColor - ctx.strokeStyle = root.strokeColor - ctx.lineWidth = root.strokeWidth + ctx.fillStyle = root.fillColor; + ctx.strokeStyle = root.strokeColor; + ctx.lineWidth = root.strokeWidth; - const count = mirroredValues.length + const count = mirroredValues.length; if (root.vertical) { // Vertical orientation - const stepY = height / (count - 1) - const centerX = width / 2 - const amplitude = width / 2 + const stepY = height / (count - 1); + const centerX = width / 2; + const amplitude = width / 2; - ctx.beginPath() + ctx.beginPath(); // Draw the left half of the waveform from top to bottom - var xOffset = mirroredValues[0] * amplitude - ctx.moveTo(centerX - xOffset, 0) + var xOffset = mirroredValues[0] * amplitude; + ctx.moveTo(centerX - xOffset, 0); for (var i = 1; i < count; i++) { - const y = i * stepY - xOffset = mirroredValues[i] * amplitude - const x = centerX - xOffset - ctx.lineTo(x, y) + const y = i * stepY; + xOffset = mirroredValues[i] * amplitude; + const x = centerX - xOffset; + ctx.lineTo(x, y); } // Draw the right half of the waveform from bottom to top to create a closed shape for (var i = count - 1; i >= 0; i--) { - const y = i * stepY - xOffset = mirroredValues[i] * amplitude - const x = centerX + xOffset // Mirrored across the center - ctx.lineTo(x, y) + const y = i * stepY; + xOffset = mirroredValues[i] * amplitude; + const x = centerX + xOffset; // Mirrored across the center + ctx.lineTo(x, y); } - ctx.closePath() + ctx.closePath(); } else { // Horizontal orientation - const stepX = width / (count - 1) - const centerY = height / 2 - const amplitude = height / 2 + const stepX = width / (count - 1); + const centerY = height / 2; + const amplitude = height / 2; - ctx.beginPath() + ctx.beginPath(); // Draw the top half of the waveform from left to right - var yOffset = mirroredValues[0] * amplitude - ctx.moveTo(0, centerY - yOffset) + var yOffset = mirroredValues[0] * amplitude; + ctx.moveTo(0, centerY - yOffset); for (var i = 1; i < count; i++) { - const x = i * stepX - yOffset = mirroredValues[i] * amplitude - const y = centerY - yOffset - ctx.lineTo(x, y) + const x = i * stepX; + yOffset = mirroredValues[i] * amplitude; + const y = centerY - yOffset; + ctx.lineTo(x, y); } // Draw the bottom half of the waveform from right to left to create a closed shape for (var i = count - 1; i >= 0; i--) { - const x = i * stepX - yOffset = mirroredValues[i] * amplitude - const y = centerY + yOffset // Mirrored across the center - ctx.lineTo(x, y) + const x = i * stepX; + yOffset = mirroredValues[i] * amplitude; + const y = centerY + yOffset; // Mirrored across the center + ctx.lineTo(x, y); } - ctx.closePath() + ctx.closePath(); } // --- Render the path --- if (root.fillColor.a > 0) { - ctx.fill() + ctx.fill(); } if (root.strokeWidth > 0) { - ctx.stroke() + ctx.stroke(); } } } diff --git a/Widgets/NBusyIndicator.qml b/Widgets/NBusyIndicator.qml index e720debe..48413b91 100644 --- a/Widgets/NBusyIndicator.qml +++ b/Widgets/NBusyIndicator.qml @@ -30,25 +30,25 @@ Item { layer.smooth: true Component.onCompleted: { - requestPaint() + requestPaint(); } onPaint: { - var ctx = getContext("2d") - ctx.reset() + var ctx = getContext("2d"); + ctx.reset(); - var centerX = width / 2 - var centerY = height / 2 - var radius = Math.min(width, height) / 2 - strokeWidth / 2 + var centerX = width / 2; + var centerY = height / 2; + var radius = Math.min(width, height) / 2 - strokeWidth / 2; - ctx.strokeStyle = root.color - ctx.lineWidth = Math.max(1, root.strokeWidth) - ctx.lineCap = "round" + ctx.strokeStyle = root.color; + ctx.lineWidth = Math.max(1, root.strokeWidth); + ctx.lineCap = "round"; // Draw arc with gap (270 degrees = 3/4 of circle) - ctx.beginPath() - ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + Math.PI * 1.5) - ctx.stroke() + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + Math.PI * 1.5); + ctx.stroke(); } } diff --git a/Widgets/NButton.qml b/Widgets/NButton.qml index ce6c68cf..3baeed65 100644 --- a/Widgets/NButton.qml +++ b/Widgets/NButton.qml @@ -39,19 +39,19 @@ Rectangle { radius: Style.radiusS color: { if (!enabled) - return outlined ? Color.transparent : Qt.lighter(Color.mSurfaceVariant, 1.2) + return outlined ? Color.transparent : Qt.lighter(Color.mSurfaceVariant, 1.2); if (hovered) - return hoverColor - return outlined ? Color.transparent : backgroundColor + return hoverColor; + return outlined ? Color.transparent : backgroundColor; } border.width: outlined ? Style.borderS : 0 border.color: { if (!enabled) - return Color.mOutline + return Color.mOutline; if (hovered) - return backgroundColor - return outlined ? backgroundColor : Color.transparent + return backgroundColor; + return outlined ? backgroundColor : Color.transparent; } opacity: enabled ? 1.0 : 0.6 @@ -87,13 +87,13 @@ Rectangle { pointSize: root.iconSize color: { if (!root.enabled) - return Color.mOnSurfaceVariant + return Color.mOnSurfaceVariant; if (root.outlined) { if (root.hovered) - return root.textColor - return root.backgroundColor + return root.textColor; + return root.backgroundColor; } - return root.textColor + return root.textColor; } Behavior on color { @@ -113,13 +113,13 @@ Rectangle { font.weight: root.fontWeight color: { if (!root.enabled) - return Color.mOnSurfaceVariant + return Color.mOnSurfaceVariant; if (root.outlined) { if (root.hovered) - return root.textColor - return root.backgroundColor + return root.textColor; + return root.backgroundColor; } - return root.textColor + return root.textColor; } Behavior on color { @@ -141,36 +141,36 @@ Rectangle { cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor onEntered: { - root.hovered = true - root.entered() + root.hovered = true; + root.entered(); if (tooltipText) { - TooltipService.show(Screen, root, root.tooltipText) + TooltipService.show(Screen, root, root.tooltipText); } } onExited: { - root.hovered = false - root.exited() + root.hovered = false; + root.exited(); if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } } onPressed: mouse => { if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } if (mouse.button === Qt.LeftButton) { - root.clicked() + root.clicked(); } else if (mouse.button == Qt.RightButton) { - root.rightClicked() + root.rightClicked(); } else if (mouse.button == Qt.MiddleButton) { - root.middleClicked() + root.middleClicked(); } } onCanceled: { - root.hovered = false + root.hovered = false; if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } } } diff --git a/Widgets/NCheckbox.qml b/Widgets/NCheckbox.qml index 5da2ae4c..57d92043 100644 --- a/Widgets/NCheckbox.qml +++ b/Widgets/NCheckbox.qml @@ -68,12 +68,12 @@ RowLayout { cursorShape: Qt.PointingHandCursor hoverEnabled: true onEntered: { - hovering = true - root.entered() + hovering = true; + root.entered(); } onExited: { - hovering = false - root.exited() + hovering = false; + root.exited(); } onClicked: root.toggled(!root.checked) } diff --git a/Widgets/NCircleStat.qml b/Widgets/NCircleStat.qml index ade9e360..9de5c30f 100644 --- a/Widgets/NCircleStat.qml +++ b/Widgets/NCircleStat.qml @@ -77,37 +77,37 @@ Rectangle { layer.smooth: true Component.onCompleted: { - requestPaint() + requestPaint(); } onPaint: { - const ctx = getContext("2d") - const w = width, h = height - const cx = w / 2, cy = h / 2 - const r = Math.min(w, h) / 2 - 5 * contentScale + const ctx = getContext("2d"); + const w = width, h = height; + const cx = w / 2, cy = h / 2; + const r = Math.min(w, h) / 2 - 5 * contentScale; // Rotated 90° to the right: gap at the bottom // Start at 150° and end at 390° (30°) → bottom opening - const start = Math.PI * 5 / 6 // 150° - const endBg = Math.PI * 13 / 6 // 390° (equivalent to 30°) + const start = Math.PI * 5 / 6; // 150° + const endBg = Math.PI * 13 / 6; // 390° (equivalent to 30°) - ctx.reset() - ctx.lineWidth = 6 * contentScale + ctx.reset(); + ctx.lineWidth = 6 * contentScale; // Track uses surface for stronger contrast - ctx.strokeStyle = Color.mSurface - ctx.beginPath() - ctx.arc(cx, cy, r, start, endBg) - ctx.stroke() + ctx.strokeStyle = Color.mSurface; + ctx.beginPath(); + ctx.arc(cx, cy, r, start, endBg); + ctx.stroke(); // Value arc with gradient starting at 25% - const ratio = Math.max(0, Math.min(1, root.animatedValue / 100)) - const end = start + (endBg - start) * ratio + const ratio = Math.max(0, Math.min(1, root.animatedValue / 100)); + const end = start + (endBg - start) * ratio; - ctx.strokeStyle = root.fillColor - ctx.beginPath() - ctx.arc(cx, cy, r, start, end) - ctx.stroke() + ctx.strokeStyle = root.fillColor; + ctx.beginPath(); + ctx.arc(cx, cy, r, start, end); + ctx.stroke(); } } diff --git a/Widgets/NClock.qml b/Widgets/NClock.qml index 5615aa45..8ffbebb6 100644 --- a/Widgets/NClock.qml +++ b/Widgets/NClock.qml @@ -1,9 +1,9 @@ import QtQuick import QtQuick.Layouts -import qs.Commons -import qs.Widgets import Quickshell import "../Helpers/ColorsConvert.js" as ColorsConvert +import qs.Commons +import qs.Widgets Item { id: root @@ -18,33 +18,33 @@ Item { property color clockColor: Color.mOnPrimary property color secondHandColor: { - var defaultColor = Color.mError - var bestContrast = 1.0 // 1.0 is "no contrast" - var bestColor = defaultColor - var candidates = [Color.mSecondary, Color.mTertiary, Color.mError] + var defaultColor = Color.mError; + var bestContrast = 1.0; // 1.0 is "no contrast" + var bestColor = defaultColor; + var candidates = [Color.mSecondary, Color.mTertiary, Color.mError]; - const minContrast = 1.149 + const minContrast = 1.149; for (var i = 0; i < candidates.length; i++) { - var candidate = candidates[i] - var contrastClock = ColorsConvert.getContrastRatio(candidate.toString(), clockColor.toString()) + var candidate = candidates[i]; + var contrastClock = ColorsConvert.getContrastRatio(candidate.toString(), clockColor.toString()); if (contrastClock < minContrast) { - continue + continue; } - var contrastBg = ColorsConvert.getContrastRatio(candidate.toString(), backgroundColor.toString()) + var contrastBg = ColorsConvert.getContrastRatio(candidate.toString(), backgroundColor.toString()); if (contrastBg < minContrast) { - continue + continue; } - var currentWorstContrast = Math.min(contrastBg, contrastClock) + var currentWorstContrast = Math.min(contrastBg, contrastClock); if (currentWorstContrast > bestContrast) { - bestContrast = currentWorstContrast - bestColor = candidate + bestContrast = currentWorstContrast; + bestColor = candidate; } } - return bestColor + return bestColor; } property color progressColor: root.secondHandColor @@ -60,23 +60,23 @@ Item { onLoaded: { item.now = Qt.binding(function () { - return root.now - }) + return root.now; + }); item.backgroundColor = Qt.binding(function () { - return root.backgroundColor - }) + return root.backgroundColor; + }); item.clockColor = Qt.binding(function () { - return root.clockColor - }) + return root.clockColor; + }); if (item.hasOwnProperty("secondHandColor")) { item.secondHandColor = Qt.binding(function () { - return root.secondHandColor - }) + return root.secondHandColor; + }); } if (item.hasOwnProperty("progressColor")) { item.progressColor = Qt.binding(function () { - return root.progressColor - }) + return root.progressColor; + }); } } } @@ -96,85 +96,85 @@ Item { Connections { target: Time function onNowChanged() { - clockCanvas.requestPaint() + clockCanvas.requestPaint(); } } onPaint: { - var currentTime = Time.now - var hours = currentTime.getHours() - var minutes = currentTime.getMinutes() - var seconds = currentTime.getSeconds() + var currentTime = Time.now; + var hours = currentTime.getHours(); + var minutes = currentTime.getMinutes(); + var seconds = currentTime.getSeconds(); - const markAlpha = 0.7 - var ctx = getContext("2d") - ctx.reset() - ctx.translate(width / 2, height / 2) - var radius = Math.min(width, height) / 2 + const markAlpha = 0.7; + var ctx = getContext("2d"); + ctx.reset(); + ctx.translate(width / 2, height / 2); + var radius = Math.min(width, height) / 2; // Hour marks - ctx.strokeStyle = Qt.alpha(clockColor, markAlpha) - ctx.lineWidth = 2 * Style.uiScaleRatio - var scaleFactor = 0.7 + ctx.strokeStyle = Qt.alpha(clockColor, markAlpha); + ctx.lineWidth = 2 * Style.uiScaleRatio; + var scaleFactor = 0.7; for (var i = 0; i < 12; i++) { - var scaleFactor = 0.8 + var scaleFactor = 0.8; if (i % 3 === 0) { - scaleFactor = 0.65 + scaleFactor = 0.65; } - ctx.save() - ctx.rotate(i * Math.PI / 6) - ctx.beginPath() - ctx.moveTo(0, -radius * scaleFactor) - ctx.lineTo(0, -radius) - ctx.stroke() - ctx.restore() + ctx.save(); + ctx.rotate(i * Math.PI / 6); + ctx.beginPath(); + ctx.moveTo(0, -radius * scaleFactor); + ctx.lineTo(0, -radius); + ctx.stroke(); + ctx.restore(); } // Hour hand - ctx.save() - var hourAngle = (hours % 12 + minutes / 60) * Math.PI / 6 - ctx.rotate(hourAngle) - ctx.strokeStyle = clockColor - ctx.lineWidth = 3 * Style.uiScaleRatio - ctx.lineCap = "round" - ctx.beginPath() - ctx.moveTo(0, 0) - ctx.lineTo(0, -radius * 0.6) - ctx.stroke() - ctx.restore() + ctx.save(); + var hourAngle = (hours % 12 + minutes / 60) * Math.PI / 6; + ctx.rotate(hourAngle); + ctx.strokeStyle = clockColor; + ctx.lineWidth = 3 * Style.uiScaleRatio; + ctx.lineCap = "round"; + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(0, -radius * 0.6); + ctx.stroke(); + ctx.restore(); // Minute hand - ctx.save() - var minuteAngle = (minutes + seconds / 60) * Math.PI / 30 - ctx.rotate(minuteAngle) - ctx.strokeStyle = clockColor - ctx.lineWidth = 2 * Style.uiScaleRatio - ctx.lineCap = "round" - ctx.beginPath() - ctx.moveTo(0, 0) - ctx.lineTo(0, -radius * 0.9) - ctx.stroke() - ctx.restore() + ctx.save(); + var minuteAngle = (minutes + seconds / 60) * Math.PI / 30; + ctx.rotate(minuteAngle); + ctx.strokeStyle = clockColor; + ctx.lineWidth = 2 * Style.uiScaleRatio; + ctx.lineCap = "round"; + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(0, -radius * 0.9); + ctx.stroke(); + ctx.restore(); // Second hand - ctx.save() - var secondAngle = seconds * Math.PI / 30 - ctx.rotate(secondAngle) - ctx.strokeStyle = secondHandColor - ctx.lineWidth = 1.6 * Style.uiScaleRatio - ctx.lineCap = "round" - ctx.beginPath() - ctx.moveTo(0, 0) - ctx.lineTo(0, -radius) - ctx.stroke() - ctx.restore() + ctx.save(); + var secondAngle = seconds * Math.PI / 30; + ctx.rotate(secondAngle); + ctx.strokeStyle = secondHandColor; + ctx.lineWidth = 1.6 * Style.uiScaleRatio; + ctx.lineCap = "round"; + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(0, -radius); + ctx.stroke(); + ctx.restore(); // Center dot - ctx.beginPath() - ctx.arc(0, 0, 3 * Style.uiScaleRatio, 0, 2 * Math.PI) - ctx.fillStyle = clockColor - ctx.fill() + ctx.beginPath(); + ctx.arc(0, 0, 3 * Style.uiScaleRatio, 0, 2 * Math.PI); + ctx.fillStyle = clockColor; + ctx.fill(); } Component.onCompleted: requestPaint() @@ -199,31 +199,31 @@ Item { Connections { target: Time function onNowChanged() { - const total = now.getSeconds() * 1000 + now.getMilliseconds() - secondsProgress.progress = total / 60000 + const total = now.getSeconds() * 1000 + now.getMilliseconds(); + secondsProgress.progress = total / 60000; } } onPaint: { - var ctx = getContext("2d") - var centerX = width / 2 - var centerY = height / 2 - var radius = Math.min(width, height) / 2 - 3 - ctx.reset() + var ctx = getContext("2d"); + var centerX = width / 2; + var centerY = height / 2; + var radius = Math.min(width, height) / 2 - 3; + ctx.reset(); // Background circle - ctx.beginPath() - ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI) - ctx.lineWidth = 2.5 - ctx.strokeStyle = Qt.alpha(clockColor, 0.15) - ctx.stroke() + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); + ctx.lineWidth = 2.5; + ctx.strokeStyle = Qt.alpha(clockColor, 0.15); + ctx.stroke(); // Progress arc - ctx.beginPath() - ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + progress * 2 * Math.PI) - ctx.lineWidth = 2.5 - ctx.strokeStyle = progressColor - ctx.lineCap = "round" - ctx.stroke() + ctx.beginPath(); + ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + progress * 2 * Math.PI); + ctx.lineWidth = 2.5; + ctx.strokeStyle = progressColor; + ctx.lineCap = "round"; + ctx.stroke(); } } @@ -234,8 +234,8 @@ Item { NText { text: { - var t = Settings.data.location.use12hourFormat ? I18n.locale.toString(now, "hh AP") : I18n.locale.toString(now, "HH") - return t.split(" ")[0] + var t = Settings.data.location.use12hourFormat ? I18n.locale.toString(now, "hh AP") : I18n.locale.toString(now, "HH"); + return t.split(" ")[0]; } pointSize: Style.fontSizeXS diff --git a/Widgets/NCollapsible.qml b/Widgets/NCollapsible.qml index 4520ceaf..e727143e 100644 --- a/Widgets/NCollapsible.qml +++ b/Widgets/NCollapsible.qml @@ -53,8 +53,8 @@ ColumnLayout { hoverEnabled: true onClicked: { - root.expanded = !root.expanded - root.toggled(root.expanded) + root.expanded = !root.expanded; + root.toggled(root.expanded); } // Hover effect overlay @@ -184,6 +184,6 @@ ColumnLayout { // Initialize expanded state Component.onCompleted: { - root.expanded = root.defaultExpanded + root.expanded = root.defaultExpanded; } } diff --git a/Widgets/NColorPicker.qml b/Widgets/NColorPicker.qml index d25087c4..cc8650db 100644 --- a/Widgets/NColorPicker.qml +++ b/Widgets/NColorPicker.qml @@ -27,14 +27,14 @@ Rectangle { var dialog = Qt.createComponent("NColorPickerDialog.qml").createObject(root, { "selectedColor": selectedColor, "parent": Overlay.overlay - }) + }); // Connect the dialog's signal to the picker's signal dialog.colorSelected.connect(function (color) { - root.selectedColor = color - root.colorSelected(color) - }) + root.selectedColor = color; + root.colorSelected(color); + }); - dialog.open() + dialog.open(); } RowLayout { diff --git a/Widgets/NColorPickerDialog.qml b/Widgets/NColorPickerDialog.qml index 4f142f16..80891cac 100644 --- a/Widgets/NColorPickerDialog.qml +++ b/Widgets/NColorPickerDialog.qml @@ -15,8 +15,8 @@ Popup { width: 580 height: { - const h = scrollView.implicitHeight + padding * 2 - Math.min(h, screen?.height - Style.barHeight - Style.marginL * 2) + const h = scrollView.implicitHeight + padding * 2; + Math.min(h, screen?.height - Style.barHeight - Style.marginL * 2); } padding: Style.marginXL @@ -27,78 +27,78 @@ Popup { modal: true function rgbToHsv(r, g, b) { - r /= 255 - g /= 255 - b /= 255 - var max = Math.max(r, g, b), min = Math.min(r, g, b) - var h, s, v = max - var d = max - min - s = max === 0 ? 0 : d / max + r /= 255; + g /= 255; + b /= 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + var d = max - min; + s = max === 0 ? 0 : d / max; if (max === min) { - h = 0 + h = 0; } else { switch (max) { case r: - h = (g - b) / d + (g < b ? 6 : 0) - break + h = (g - b) / d + (g < b ? 6 : 0); + break; case g: - h = (b - r) / d + 2 - break + h = (b - r) / d + 2; + break; case b: - h = (r - g) / d + 4 - break + h = (r - g) / d + 4; + break; } - h /= 6 + h /= 6; } - return [h * 360, s * 100, v * 100] + return [h * 360, s * 100, v * 100]; } function hsvToRgb(h, s, v) { - h /= 360 - s /= 100 - v /= 100 + h /= 360; + s /= 100; + v /= 100; - var r, g, b - var i = Math.floor(h * 6) - var f = h * 6 - i - var p = v * (1 - s) - var q = v * (1 - f * s) - var t = v * (1 - (1 - f) * s) + var r, g, b; + var i = Math.floor(h * 6); + var f = h * 6 - i; + var p = v * (1 - s); + var q = v * (1 - f * s); + var t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: - r = v - g = t - b = p - break + r = v; + g = t; + b = p; + break; case 1: - r = q - g = v - b = p - break + r = q; + g = v; + b = p; + break; case 2: - r = p - g = v - b = t - break + r = p; + g = v; + b = t; + break; case 3: - r = p - g = q - b = v - break + r = p; + g = q; + b = v; + break; case 4: - r = t - g = p - b = v - break + r = t; + g = p; + b = v; + break; case 5: - r = v - g = p - b = q - break + r = v; + g = p; + b = q; + break; } - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)] + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; } background: Rectangle { @@ -207,7 +207,7 @@ Popup { Layout.fillWidth: true onEditingFinished: { if (/^#[0-9A-F]{6}$/i.test(text)) { - root.selectedColor = text + root.selectedColor = text; } } } @@ -247,10 +247,10 @@ Popup { to: 255 value: Math.round(root.selectedColor.r * 255) onMoved: value => { - root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1) - var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) - root.currentHue = hsv[0] - root.currentSaturation = hsv[1] + root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1); + var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255); + root.currentHue = hsv[0]; + root.currentSaturation = hsv[1]; } text: Math.round(value) } @@ -273,11 +273,11 @@ Popup { to: 255 value: Math.round(root.selectedColor.g * 255) onMoved: value => { - root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1) + root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1); // Update stored hue and saturation when RGB changes - var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) - root.currentHue = hsv[0] - root.currentSaturation = hsv[1] + var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255); + root.currentHue = hsv[0]; + root.currentSaturation = hsv[1]; } text: Math.round(value) } @@ -300,11 +300,11 @@ Popup { to: 255 value: Math.round(root.selectedColor.b * 255) onMoved: value => { - root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1) + root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1); // Update stored hue and saturation when RGB changes - var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) - root.currentHue = hsv[0] - root.currentSaturation = hsv[1] + var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255); + root.currentHue = hsv[0]; + root.currentSaturation = hsv[1]; } text: Math.round(value) } @@ -326,23 +326,23 @@ Popup { from: 0 to: 100 value: { - var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) - return hsv[2] + var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255); + return hsv[2]; } onMoved: value => { - var hue = root.currentHue - var saturation = root.currentSaturation + var hue = root.currentHue; + var saturation = root.currentSaturation; if (hue === 0 && saturation === 0) { - var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) - hue = hsv[0] - saturation = hsv[1] - root.currentHue = hue - root.currentSaturation = saturation + var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255); + hue = hsv[0]; + saturation = hsv[1]; + root.currentHue = hue; + root.currentSaturation = saturation; } - var rgb = root.hsvToRgb(hue, saturation, value) - root.selectedColor = Qt.rgba(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1) + var rgb = root.hsvToRgb(hue, saturation, value); + root.selectedColor = Qt.rgba(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1); } text: Math.round(brightnessSlider.value) + "%" } @@ -386,10 +386,10 @@ Popup { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - root.selectedColor = modelData - var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) - root.currentHue = hsv[0] - root.currentSaturation = hsv[1] + root.selectedColor = modelData; + var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255); + root.currentHue = hsv[0]; + root.currentSaturation = hsv[1]; } } } @@ -421,7 +421,8 @@ Popup { flow: Flow.LeftToRight Repeater { - model: ["#F44336", "#E91E63", "#9C27B0", "#673AB7", "#3F51B5", "#2196F3", "#03A9F4", "#00BCD4", "#009688", "#4CAF50", "#8BC34A", "#CDDC39", "#FFEB3B", "#FFC107", "#FF9800", "#FF5722", "#795548", "#9E9E9E", "#E74C3C", "#E67E22", "#F1C40F", "#2ECC71", "#1ABC9C", "#3498DB", "#2980B9", "#9B59B6", "#34495E", "#2C3E50", "#95A5A6", "#7F8C8D", Color.white, Color.black] + model: ["#F44336", "#E91E63", "#9C27B0", "#673AB7", "#3F51B5", "#2196F3", "#03A9F4", "#00BCD4", "#009688", "#4CAF50", "#8BC34A", "#CDDC39", "#FFEB3B", "#FFC107", "#FF9800", "#FF5722", "#795548", "#9E9E9E", "#E74C3C", "#E67E22", "#F1C40F", "#2ECC71", "#1ABC9C", "#3498DB", "#2980B9", "#9B59B6", "#34495E", "#2C3E50", "#95A5A6", "#7F8C8D", + Color.white, Color.black] Rectangle { width: 24 @@ -435,10 +436,10 @@ Popup { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - root.selectedColor = modelData - var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) - root.currentHue = hsv[0] - root.currentSaturation = hsv[1] + root.selectedColor = modelData; + var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255); + root.currentHue = hsv[0]; + root.currentSaturation = hsv[1]; } } } @@ -462,7 +463,7 @@ Popup { text: I18n.tr("widgets.color-picker.cancel") outlined: cancelButton.hovered ? false : true onClicked: { - root.close() + root.close(); } } @@ -470,8 +471,8 @@ Popup { text: I18n.tr("widgets.color-picker.apply") icon: "check" onClicked: { - root.colorSelected(root.selectedColor) - root.close() + root.colorSelected(root.selectedColor); + root.close(); } } } diff --git a/Widgets/NComboBox.qml b/Widgets/NComboBox.qml index b0c7faed..7fead277 100644 --- a/Widgets/NComboBox.qml +++ b/Widgets/NComboBox.qml @@ -25,31 +25,31 @@ RowLayout { function itemCount() { if (!root.model) - return 0 + return 0; if (typeof root.model.count === 'number') - return root.model.count + return root.model.count; if (Array.isArray(root.model)) - return root.model.length - return 0 + return root.model.length; + return 0; } function getItem(index) { if (!root.model) - return null + return null; if (typeof root.model.get === 'function') - return root.model.get(index) + return root.model.get(index); if (Array.isArray(root.model)) - return root.model[index] - return null + return root.model[index]; + return null; } function findIndexByKey(key) { for (var i = 0; i < itemCount(); i++) { - var item = getItem(i) + var item = getItem(i); if (item && item.key === key) - return i + return i; } - return -1 + return -1; } NLabel { @@ -65,9 +65,9 @@ RowLayout { model: model currentIndex: findIndexByKey(currentKey) onActivated: { - var item = getItem(combo.currentIndex) + var item = getItem(combo.currentIndex); if (item && item.key !== undefined) - root.selected(item.key) + root.selected(item.key); } background: Rectangle { @@ -123,16 +123,16 @@ RowLayout { onHoveredChanged: { if (hovered) { - ListView.view.currentIndex = itemIndex + ListView.view.currentIndex = itemIndex; } } onClicked: { - var item = root.getItem(itemIndex) + var item = root.getItem(itemIndex); if (item && item.key !== undefined && parentComboBox) { - root.selected(item.key) - parentComboBox.currentIndex = itemIndex - parentComboBox.popup.close() + root.selected(item.key); + parentComboBox.currentIndex = itemIndex; + parentComboBox.popup.close(); } } @@ -149,8 +149,8 @@ RowLayout { contentItem: NText { text: { - var item = root.getItem(index) - return item && item.name ? item.name : "" + var item = root.getItem(index); + return item && item.name ? item.name : ""; } pointSize: Style.fontSizeM color: highlighted ? Color.mOnHover : Color.mOnSurface @@ -177,7 +177,7 @@ RowLayout { Connections { target: root function onCurrentKeyChanged() { - combo.currentIndex = root.findIndexByKey(currentKey) + combo.currentIndex = root.findIndexByKey(currentKey); } } } diff --git a/Widgets/NContextMenu.qml b/Widgets/NContextMenu.qml index eed0a423..52c7b8b9 100644 --- a/Widgets/NContextMenu.qml +++ b/Widgets/NContextMenu.qml @@ -90,8 +90,8 @@ Popup { onClicked: { if (enabled) { - popup.triggered(modelData.action || modelData.key || index.toString()) - popup.close() + popup.triggered(modelData.action || modelData.key || index.toString()); + popup.close(); } } } @@ -99,14 +99,14 @@ Popup { // Helper function to open at mouse position function openAt(x, y) { - root.x = x - root.y = y - root.open() + root.x = x; + root.y = y; + root.open(); } // Helper function to open at item function openAtItem(item, mouseX, mouseY) { - var pos = item.mapToItem(root.parent, mouseX || 0, mouseY || 0) - openAt(pos.x, pos.y) + var pos = item.mapToItem(root.parent, mouseX || 0, mouseY || 0); + openAt(pos.x, pos.y); } } diff --git a/Widgets/NDateTimeTokens.qml b/Widgets/NDateTimeTokens.qml index 99bcb409..b13e1a59 100644 --- a/Widgets/NDateTimeTokens.qml +++ b/Widgets/NDateTimeTokens.qml @@ -25,151 +25,179 @@ Rectangle { id: tokensList Layout.fillWidth: true Layout.fillHeight: true - model: [// Common format combinations + model: [ + // Common format combinations { "category": "Common", "token": "h:mm AP", "description": I18n.tr("widgets.datetime-tokens.common.12hour-time-minutes"), "example": "2:30 PM" - }, { + }, + { "category": "Common", "token": "HH:mm", "description": I18n.tr("widgets.datetime-tokens.common.24hour-time-minutes"), "example": "14:30" - }, { + }, + { "category": "Common", "token": "HH:mm:ss", "description": I18n.tr("widgets.datetime-tokens.common.24hour-time-seconds"), "example": "14:30:45" - }, { + }, + { "category": "Common", "token": "ddd MMM d", "description": I18n.tr("widgets.datetime-tokens.common.weekday-month-day"), "example": "Mon Dec 25" - }, { + }, + { "category": "Common", "token": "yyyy-MM-dd", "description": I18n.tr("widgets.datetime-tokens.common.iso-date"), "example": "2023-12-25" - }, { + }, + { "category": "Common", "token": "MM/dd/yyyy", "description": I18n.tr("widgets.datetime-tokens.common.us-date"), "example": "12/25/2023" - }, { + }, + { "category": "Common", "token": "dd.MM.yyyy", "description": I18n.tr("widgets.datetime-tokens.common.european-date"), "example": "25.12.2023" - }, { + }, + { "category": "Common", "token": "ddd, MMM dd", "description": I18n.tr("widgets.datetime-tokens.common.weekday-date"), "example": "Fri, Dec 12" - }, // Hour tokens + } // Hour tokens + , { "category": "Hour", "token": "H", "description": I18n.tr("widgets.datetime-tokens.hour.no-leading-zero"), "example": "14" - }, { + }, + { "category": "Hour", "token": "HH", "description": I18n.tr("widgets.datetime-tokens.hour.leading-zero"), "example": "14" - }, // Minute tokens + } // Minute tokens + , { "category": "Minute", "token": "m", "description": I18n.tr("widgets.datetime-tokens.minute.no-leading-zero"), "example": "30" - }, { + }, + { "category": "Minute", "token": "mm", "description": I18n.tr("widgets.datetime-tokens.minute.leading-zero"), "example": "30" - }, // Second tokens + } // Second tokens + , { "category": "Second", "token": "s", "description": I18n.tr("widgets.datetime-tokens.second.no-leading-zero"), "example": "45" - }, { + }, + { "category": "Second", "token": "ss", "description": I18n.tr("widgets.datetime-tokens.second.leading-zero"), "example": "45" - }, // AM/PM tokens + } // AM/PM tokens + , { "category": "AM/PM", "token": "AP", "description": I18n.tr("widgets.datetime-tokens.ampm.uppercase"), "example": "PM" - }, { + }, + { "category": "AM/PM", "token": "ap", "description": I18n.tr("widgets.datetime-tokens.ampm.lowercase"), "example": "pm" - }, // Timezone tokens + } // Timezone tokens + , { "category": "Timezone", "token": "t", "description": I18n.tr("widgets.datetime-tokens.timezone.abbreviation"), "example": "UTC" - }, // Year tokens + } // Year tokens + , { "category": "Year", "token": "yy", "description": I18n.tr("widgets.datetime-tokens.year.two-digit"), "example": "23" - }, { + }, + { "category": "Year", "token": "yyyy", "description": I18n.tr("widgets.datetime-tokens.year.four-digit"), "example": "2023" - }, // Month tokens + } // Month tokens + , { "category": "Month", "token": "M", "description": I18n.tr("widgets.datetime-tokens.month.number-no-zero"), "example": "12" - }, { + }, + { "category": "Month", "token": "MM", "description": I18n.tr("widgets.datetime-tokens.month.number-leading-zero"), "example": "12" - }, { + }, + { "category": "Month", "token": "MMM", "description": I18n.tr("widgets.datetime-tokens.month.abbreviated"), "example": "Dec" - }, { + }, + { "category": "Month", "token": "MMMM", "description": I18n.tr("widgets.datetime-tokens.month.full"), "example": "December" - }, // Day tokens + } // Day tokens + , { "category": "Day", "token": "d", "description": I18n.tr("widgets.datetime-tokens.day.no-leading-zero"), "example": "25" - }, { + }, + { "category": "Day", "token": "dd", "description": I18n.tr("widgets.datetime-tokens.day.leading-zero"), "example": "25" - }, { + }, + { "category": "Day", "token": "ddd", "description": I18n.tr("widgets.datetime-tokens.day.abbreviated"), "example": "Mon" - }, { + }, + { "category": "Day", "token": "dddd", "description": I18n.tr("widgets.datetime-tokens.day.full"), "example": "Monday" - }] + } + ] delegate: Rectangle { id: tokenDelegate @@ -178,9 +206,9 @@ Rectangle { radius: Style.radiusS color: { if (tokenMouseArea.containsMouse) { - return Qt.alpha(Color.mPrimary, 0.1) + return Qt.alpha(Color.mPrimary, 0.1); } - return index % 2 === 0 ? Color.mSurfaceVariant : Qt.alpha(Color.mSurfaceVariant, 0.6) + return index % 2 === 0 ? Color.mSurfaceVariant : Qt.alpha(Color.mSurfaceVariant, 0.6); } // Mouse area for the entire delegate @@ -191,8 +219,8 @@ Rectangle { cursorShape: Qt.PointingHandCursor onClicked: { - root.tokenClicked(modelData.token) - clickAnimation.start() + root.tokenClicked(modelData.token); + clickAnimation.start(); } } @@ -331,25 +359,25 @@ Rectangle { function getCategoryColor(category) { switch (category) { case "Year": - return [Color.mPrimary, Color.mOnPrimary] + return [Color.mPrimary, Color.mOnPrimary]; case "Month": - return [Color.mSecondary, Color.mOnSecondary] + return [Color.mSecondary, Color.mOnSecondary]; case "Day": - return [Color.mTertiary, Color.mOnTertiary] + return [Color.mTertiary, Color.mOnTertiary]; case "Hour": - return [Color.mPrimary, Color.mOnPrimary] + return [Color.mPrimary, Color.mOnPrimary]; case "Minute": - return [Color.mSecondary, Color.mOnSecondary] + return [Color.mSecondary, Color.mOnSecondary]; case "Second": - return [Color.mTertiary, Color.mOnTertiary] + return [Color.mTertiary, Color.mOnTertiary]; case "AM/PM": - return [Color.mError, Color.mOnError] + return [Color.mError, Color.mOnError]; case "Timezone": - return [Color.mOnSurface, Color.mSurface] + return [Color.mOnSurface, Color.mSurface]; case "Common": - return [Color.mError, Color.mOnError] + return [Color.mError, Color.mOnError]; default: - return [Color.mOnSurfaceVariant, Color.mSurfaceVariant] + return [Color.mOnSurfaceVariant, Color.mSurfaceVariant]; } } } diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index 84eb473d..963603b9 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -1,12 +1,12 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls import Qt.labs.folderlistmodel +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Io +import "../Helpers/FuzzySort.js" as FuzzySort import qs.Commons import qs.Widgets -import "../Helpers/FuzzySort.js" as FuzzySort Popup { id: root @@ -29,13 +29,13 @@ Popup { function openFilePicker() { if (!root.currentPath) - root.currentPath = root.initialPath - shouldResetSelection = true - open() + root.currentPath = root.initialPath; + shouldResetSelection = true; + open(); } function getFileIcon(fileName) { - const ext = fileName.split('.').pop().toLowerCase() + const ext = fileName.split('.').pop().toLowerCase(); const iconMap = { "txt": 'filepicker-file-text', "md": 'filepicker-file-text', @@ -76,54 +76,52 @@ Popup { "app": 'filepicker-settings', "deb": 'filepicker-settings', "rpm": 'filepicker-settings' - } - return iconMap[ext] || 'filepicker-file' + }; + return iconMap[ext] || 'filepicker-file'; } function formatFileSize(bytes) { if (bytes === 0) - return "0 B" - const k = 1024, sizes = ["B", "KB", "MB", "GB", "TB"] - const i = Math.floor(Math.log(bytes) / Math.log(k)) - return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i] + return "0 B"; + const k = 1024, sizes = ["B", "KB", "MB", "GB", "TB"]; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i]; } function confirmSelection() { if (filePickerPanel.currentSelection.length === 0) - return - - root.selectedPaths = filePickerPanel.currentSelection - root.accepted(filePickerPanel.currentSelection) - root.close() + return; + root.selectedPaths = filePickerPanel.currentSelection; + root.accepted(filePickerPanel.currentSelection); + root.close(); } function updateFilteredModel() { - filteredModel.clear() - const searchText = filePickerPanel.filterText.toLowerCase() + filteredModel.clear(); + const searchText = filePickerPanel.filterText.toLowerCase(); for (var i = 0; i < folderModel.count; i++) { - const fileName = folderModel.get(i, "fileName") - const filePath = folderModel.get(i, "filePath") - const fileIsDir = folderModel.get(i, "fileIsDir") - const fileSize = folderModel.get(i, "fileSize") + const fileName = folderModel.get(i, "fileName"); + const filePath = folderModel.get(i, "filePath"); + const fileIsDir = folderModel.get(i, "fileIsDir"); + const fileSize = folderModel.get(i, "fileSize"); // Skip hidden items if showHiddenFiles is false // This additional check ensures hidden files are properly filtered if (!root.showHiddenFiles && fileName.startsWith(".")) { - continue + continue; } // In folder mode, hide files if (root.selectionMode === "folders" && !fileIsDir) - continue - + continue; if (searchText === "" || fileName.toLowerCase().includes(searchText)) { filteredModel.append({ "fileName": fileName, "filePath": filePath, "fileIsDir": fileIsDir, "fileSize": fileSize - }) + }); } } } @@ -157,16 +155,16 @@ Popup { Keys.onPressed: event => { if (event.modifiers & Qt.ControlModifier && event.key === Qt.Key_F) { - filePickerPanel.showSearchBar = !filePickerPanel.showSearchBar + filePickerPanel.showSearchBar = !filePickerPanel.showSearchBar; if (filePickerPanel.showSearchBar) - Qt.callLater(() => searchInput.forceActiveFocus()) - event.accepted = true + Qt.callLater(() => searchInput.forceActiveFocus()); + event.accepted = true; } else if (event.key === Qt.Key_Escape && filePickerPanel.showSearchBar) { - filePickerPanel.showSearchBar = false - filePickerPanel.searchText = "" - filePickerPanel.filterText = "" - root.updateFilteredModel() - event.accepted = true + filePickerPanel.showSearchBar = false; + filePickerPanel.searchText = ""; + filePickerPanel.filterText = ""; + root.updateFilteredModel(); + event.accepted = true; } } @@ -198,8 +196,8 @@ Popup { icon: "filepicker-folder-current" visible: root.selectionMode === "folders" onClicked: { - filePickerPanel.currentSelection = [root.currentPath] - root.confirmSelection() + filePickerPanel.currentSelection = [root.currentPath]; + root.confirmSelection(); } } @@ -208,18 +206,18 @@ Popup { tooltipText: I18n.tr("tooltips.refresh") onClicked: { // Force a proper refresh by resetting the folder - const currentFolder = folderModel.folder - folderModel.folder = "" - folderModel.folder = currentFolder - Qt.callLater(root.updateFilteredModel) + const currentFolder = folderModel.folder; + folderModel.folder = ""; + folderModel.folder = currentFolder; + Qt.callLater(root.updateFilteredModel); } } NIconButton { icon: "filepicker-close" tooltipText: I18n.tr("tooltips.close") onClicked: { - root.cancelled() - root.close() + root.cancelled(); + root.close(); } } } @@ -251,9 +249,9 @@ Popup { baseSize: Style.baseWidgetSize * 0.8 enabled: folderModel.folder.toString() !== "file:///" onClicked: { - const parentPath = folderModel.parentFolder.toString().replace("file://", "") - folderModel.folder = "file://" + parentPath - root.currentPath = parentPath + const parentPath = folderModel.parentFolder.toString().replace("file://", ""); + folderModel.folder = "file://" + parentPath; + root.currentPath = parentPath; } } @@ -262,9 +260,9 @@ Popup { tooltipText: I18n.tr("tooltips.home") baseSize: Style.baseWidgetSize * 0.8 onClicked: { - const homePath = Quickshell.env("HOME") || "/home" - folderModel.folder = "file://" + homePath - root.currentPath = homePath + const homePath = Quickshell.env("HOME") || "/home"; + folderModel.folder = "file://" + homePath; + root.currentPath = homePath; } } @@ -273,11 +271,11 @@ Popup { tooltipText: filePickerPanel.showSearchBar ? "Close Search" : "Search" baseSize: Style.baseWidgetSize * 0.8 onClicked: { - filePickerPanel.showSearchBar = !filePickerPanel.showSearchBar + filePickerPanel.showSearchBar = !filePickerPanel.showSearchBar; if (!filePickerPanel.showSearchBar) { - filePickerPanel.searchText = "" - filePickerPanel.filterText = "" - root.updateFilteredModel() + filePickerPanel.searchText = ""; + filePickerPanel.filterText = ""; + root.updateFilteredModel(); } } } @@ -292,19 +290,19 @@ Popup { enabled: !filePickerPanel.showSearchBar onEditingFinished: { - const newPath = text.trim() + const newPath = text.trim(); if (newPath !== "" && newPath !== root.currentPath) { - folderModel.folder = "file://" + newPath - root.currentPath = newPath + folderModel.folder = "file://" + newPath; + root.currentPath = newPath; } else { - text = root.currentPath + text = root.currentPath; } } Connections { target: root function onCurrentPathChanged() { if (!locationInput.activeFocus) - locationInput.text = root.currentPath + locationInput.text = root.currentPath; } } } @@ -321,15 +319,15 @@ Popup { text: filePickerPanel.searchText onTextChanged: { - filePickerPanel.searchText = text - filePickerPanel.filterText = text - root.updateFilteredModel() + filePickerPanel.searchText = text; + filePickerPanel.filterText = text; + root.updateFilteredModel(); } Keys.onEscapePressed: { - filePickerPanel.showSearchBar = false - filePickerPanel.searchText = "" - filePickerPanel.filterText = "" - root.updateFilteredModel() + filePickerPanel.showSearchBar = false; + filePickerPanel.searchText = ""; + filePickerPanel.filterText = ""; + root.updateFilteredModel(); } } @@ -344,12 +342,12 @@ Popup { tooltipText: root.showHiddenFiles ? "Hide Hidden Files" : "Show Hidden Files" baseSize: Style.baseWidgetSize * 0.8 onClicked: { - root.showHiddenFiles = !root.showHiddenFiles + root.showHiddenFiles = !root.showHiddenFiles; // Force model refresh by resetting the folder - const currentFolder = folderModel.folder - folderModel.folder = "" - folderModel.folder = currentFolder - Qt.callLater(root.updateFilteredModel) + const currentFolder = folderModel.folder; + folderModel.folder = ""; + folderModel.folder = currentFolder; + Qt.callLater(root.updateFilteredModel); } } } @@ -376,19 +374,19 @@ Popup { sortReversed: false onFolderChanged: { - root.currentPath = folder.toString().replace("file://", "") - filePickerPanel.currentSelection = [] - Qt.callLater(root.updateFilteredModel) + root.currentPath = folder.toString().replace("file://", ""); + filePickerPanel.currentSelection = []; + Qt.callLater(root.updateFilteredModel); } onStatusChanged: { if (status === FolderListModel.Error) { if (root.currentPath !== Quickshell.env("HOME")) { - folder = "file://" + Quickshell.env("HOME") - root.currentPath = Quickshell.env("HOME") + folder = "file://" + Quickshell.env("HOME"); + root.currentPath = Quickshell.env("HOME"); } } else if (status === FolderListModel.Ready) { - root.updateFilteredModel() + root.updateFilteredModel(); } } } @@ -397,7 +395,7 @@ Popup { Connections { target: root function onShowHiddenFilesChanged() { - folderModel.nameFilters = root.showHiddenFiles ? ["*", ".*"] : root.nameFilters + folderModel.nameFilters = root.showHiddenFiles ? ["*", ".*"] : root.nameFilters; } } @@ -523,9 +521,9 @@ Popup { property bool isImage: { if (model.fileIsDir) - return false - const ext = model.fileName.split('.').pop().toLowerCase() - return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'ico'].includes(ext) + return false; + const ext = model.fileName.split('.').pop().toLowerCase(); + return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'ico'].includes(ext); } Image { @@ -542,7 +540,7 @@ Popup { sourceSize.height: 120 onStatusChanged: { if (status === Image.Error) - visible = false + visible = false; } Rectangle { @@ -564,11 +562,11 @@ Popup { pointSize: Style.fontSizeXXL * 2 color: { if (isSelected) - return Color.mSecondary + return Color.mSecondary; else if (mouseArea.containsMouse) - return Color.mOnHover + return Color.mOnHover; else - return model.fileIsDir ? Color.mPrimary : Color.mOnSurfaceVariant + return model.fileIsDir ? Color.mPrimary : Color.mOnSurfaceVariant; } anchors.centerIn: parent visible: !iconContainer.isImage || thumbnail.status !== Image.Ready @@ -598,11 +596,11 @@ Popup { text: model.fileName color: { if (isSelected) - return Color.mSecondary + return Color.mSecondary; else if (mouseArea.containsMouse) - return Color.mOnHover + return Color.mOnHover; else - return Color.mOnSurfaceVariant + return Color.mOnSurfaceVariant; } pointSize: Style.fontSizeS font.weight: isSelected ? Style.fontWeightBold : Style.fontWeightRegular @@ -625,13 +623,13 @@ Popup { if (model.fileIsDir) { // In folder mode, single click selects the folder if (root.selectionMode === "folders") { - filePickerPanel.currentSelection = [model.filePath] + filePickerPanel.currentSelection = [model.filePath]; } // In file mode, single click on folder does nothing (must double-click to enter) } else { // Single click on file selects it (only in file mode) if (root.selectionMode === "files") { - filePickerPanel.currentSelection = [model.filePath] + filePickerPanel.currentSelection = [model.filePath]; } } } @@ -641,13 +639,13 @@ Popup { if (mouse.button === Qt.LeftButton) { if (model.fileIsDir) { // Double-click on folder always navigates into it - folderModel.folder = "file://" + model.filePath - root.currentPath = model.filePath + folderModel.folder = "file://" + model.filePath; + root.currentPath = model.filePath; } else { // Double-click on file selects and confirms (only in file mode) if (root.selectionMode === "files") { - filePickerPanel.currentSelection = [model.filePath] - root.confirmSelection() + filePickerPanel.currentSelection = [model.filePath]; + root.confirmSelection(); } } } @@ -670,10 +668,10 @@ Popup { height: 40 color: { if (filePickerPanel.currentSelection.includes(model.filePath)) - return Color.mSecondary + return Color.mSecondary; if (mouseArea.containsMouse) - return Color.mHover - return Color.transparent + return Color.mHover; + return Color.transparent; } radius: Style.radiusS Behavior on color { @@ -723,13 +721,13 @@ Popup { if (model.fileIsDir) { // In folder mode, single click selects the folder if (root.selectionMode === "folders") { - filePickerPanel.currentSelection = [model.filePath] + filePickerPanel.currentSelection = [model.filePath]; } // In file mode, single click on folder does nothing (must double-click to enter) } else { // Single click on file selects it (only in file mode) if (root.selectionMode === "files") { - filePickerPanel.currentSelection = [model.filePath] + filePickerPanel.currentSelection = [model.filePath]; } } } @@ -739,13 +737,13 @@ Popup { if (mouse.button === Qt.LeftButton) { if (model.fileIsDir) { // Double-click on folder always navigates into it - folderModel.folder = "file://" + model.filePath - root.currentPath = model.filePath + folderModel.folder = "file://" + model.filePath; + root.currentPath = model.filePath; } else { // Double-click on file selects and confirms (only in file mode) if (root.selectionMode === "files") { - filePickerPanel.currentSelection = [model.filePath] - root.confirmSelection() + filePickerPanel.currentSelection = [model.filePath]; + root.confirmSelection(); } } } @@ -763,12 +761,12 @@ Popup { NText { text: { if (filePickerPanel.searchText.length > 0) { - return "Searching for: \"" + filePickerPanel.searchText + "\" (" + filteredModel.count + " matches)" + return "Searching for: \"" + filePickerPanel.searchText + "\" (" + filteredModel.count + " matches)"; } else if (filePickerPanel.currentSelection.length > 0) { - const selectedName = filePickerPanel.currentSelection[0].split('/').pop() - return "Selected: " + selectedName + const selectedName = filePickerPanel.currentSelection[0].split('/').pop(); + return "Selected: " + selectedName; } else { - return filteredModel.count + " items" + return filteredModel.count + " items"; } } color: filePickerPanel.searchText.length > 0 ? Color.mPrimary : Color.mOnSurfaceVariant @@ -780,8 +778,8 @@ Popup { text: I18n.tr("widgets.file-picker.cancel") outlined: true onClicked: { - root.cancelled() - root.close() + root.cancelled(); + root.close(); } } @@ -798,16 +796,16 @@ Popup { target: root function onShouldResetSelectionChanged() { if (root.shouldResetSelection) { - filePickerPanel.currentSelection = [] - root.shouldResetSelection = false + filePickerPanel.currentSelection = []; + root.shouldResetSelection = false; } } } Component.onCompleted: { if (!root.currentPath) - root.currentPath = root.initialPath - folderModel.folder = "file://" + root.currentPath + root.currentPath = root.initialPath; + folderModel.folder = "file://" + root.currentPath; } } } diff --git a/Widgets/NIcon.qml b/Widgets/NIcon.qml index 32e274f2..371c1867 100644 --- a/Widgets/NIcon.qml +++ b/Widgets/NIcon.qml @@ -13,14 +13,14 @@ Text { visible: (icon !== undefined) && (icon !== "") text: { if ((icon === undefined) || (icon === "")) { - return "" + return ""; } if (Icons.get(icon) === undefined) { - Logger.w("Icon", `"${icon}"`, "doesn't exist in the icons font") - Logger.callStack() - return Icons.get(Icons.defaultIcon) + Logger.w("Icon", `"${icon}"`, "doesn't exist in the icons font"); + Logger.callStack(); + return Icons.get(Icons.defaultIcon); } - return Icons.get(icon) + return Icons.get(icon); } font.family: Icons.fontFamily font.pointSize: applyUiScale ? root.pointSize * Style.uiScaleRatio : root.pointSize diff --git a/Widgets/NIconButton.qml b/Widgets/NIconButton.qml index eee7523e..7ec3d521 100644 --- a/Widgets/NIconButton.qml +++ b/Widgets/NIconButton.qml @@ -53,9 +53,9 @@ Rectangle { pointSize: { switch (root.density) { case "compact": - return Math.max(1, root.width * 0.65) + return Math.max(1, root.width * 0.65); default: - return Math.max(1, root.width * 0.48) + return Math.max(1, root.width * 0.48); } } applyUiScale: root.applyUiScale @@ -81,32 +81,32 @@ Rectangle { acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton hoverEnabled: true onEntered: { - hovering = root.enabled ? true : false + hovering = root.enabled ? true : false; if (tooltipText) { - TooltipService.show(Screen, parent, tooltipText, tooltipDirection) + TooltipService.show(Screen, parent, tooltipText, tooltipDirection); } - root.entered() + root.entered(); } onExited: { - hovering = false + hovering = false; if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } - root.exited() + root.exited(); } onClicked: function (mouse) { if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } if (!root.enabled && !allowClickWhenDisabled) { - return + return; } if (mouse.button === Qt.LeftButton) { - root.clicked() + root.clicked(); } else if (mouse.button === Qt.RightButton) { - root.rightClicked() + root.rightClicked(); } else if (mouse.button === Qt.MiddleButton) { - root.middleClicked() + root.middleClicked(); } } onWheel: wheel => root.wheel(wheel.angleDelta.y) diff --git a/Widgets/NIconButtonHot.qml b/Widgets/NIconButtonHot.qml index 481d526f..d40a0329 100644 --- a/Widgets/NIconButtonHot.qml +++ b/Widgets/NIconButtonHot.qml @@ -1,7 +1,7 @@ import QtQuick import QtQuick.Controls -import QtQuick.Layouts import QtQuick.Effects +import QtQuick.Layouts import qs.Commons import qs.Services.UI @@ -50,15 +50,15 @@ Rectangle { opacity: root.enabled ? Style.opacityFull : Style.opacityMedium color: { if (pressed) { - return colorBgHover + return colorBgHover; } if (hot) { - return colorBgHot + return colorBgHot; } if (root.enabled && root.hovering) { - return colorBgHover + return colorBgHover; } - return colorBg + return colorBg; } radius: width * 0.5 border.color: root.enabled && root.hovering ? colorBorderHover : colorBorder @@ -85,15 +85,15 @@ Rectangle { applyUiScale: root.applyUiScale color: { if (pressed) { - return colorFgHover + return colorFgHover; } if (hot) { - return colorFgHot + return colorFgHot; } if (root.enabled && root.hovering) { - return colorFgHover + return colorFgHover; } - return colorFg + return colorFg; } // Center horizontally x: (root.width - width) / 2 @@ -117,57 +117,57 @@ Rectangle { hoverEnabled: true onEntered: { - hovering = root.enabled ? true : false + hovering = root.enabled ? true : false; if (tooltipText) { - TooltipService.show(Screen, parent, tooltipText, tooltipDirection) + TooltipService.show(Screen, parent, tooltipText, tooltipDirection); } - root.entered() + root.entered(); } onExited: { - hovering = false + hovering = false; if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } - root.exited() + root.exited(); } onPressed: function (mouse) { if (root.enabled) { - root.pressed = true - root.scale = 0.92 + root.pressed = true; + root.scale = 0.92; } if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } } onReleased: function (mouse) { - root.scale = 1.0 - root.pressed = false + root.scale = 1.0; + root.pressed = false; if (!root.enabled && !allowClickWhenDisabled) { - return + return; } // Only trigger actions if released while hovering if (root.hovering) { if (mouse.button === Qt.LeftButton) { - root.clicked() + root.clicked(); } else if (mouse.button === Qt.RightButton) { - root.rightClicked() + root.rightClicked(); } else if (mouse.button === Qt.MiddleButton) { - root.middleClicked() + root.middleClicked(); } } } onCanceled: { - root.hovering = false - root.pressed = false - root.scale = 1.0 + root.hovering = false; + root.pressed = false; + root.scale = 1.0; if (tooltipText) { - TooltipService.hide() + TooltipService.hide(); } } } diff --git a/Widgets/NIconPicker.qml b/Widgets/NIconPicker.qml index f37e01f7..bd9eb1bb 100644 --- a/Widgets/NIconPicker.qml +++ b/Widgets/NIconPicker.qml @@ -23,18 +23,18 @@ Popup { property var allIcons: Object.keys(Icons.icons) property var filteredIcons: { if (query === "") - return allIcons - var q = query.toLowerCase() - return allIcons.filter(name => name.toLowerCase().includes(q)) + return allIcons; + var q = query.toLowerCase(); + return allIcons.filter(name => name.toLowerCase().includes(q)); } readonly property int columns: 6 readonly property int cellW: Math.floor(grid.width / columns) readonly property int cellH: Math.round(cellW * 0.7 + 36) onOpened: { - selectedIcon = initialIcon - query = initialIcon - searchInput.forceActiveFocus() + selectedIcon = initialIcon; + query = initialIcon; + searchInput.forceActiveFocus(); } background: Rectangle { @@ -105,9 +105,9 @@ Popup { anchors.fill: parent onClicked: root.selectedIcon = modelData onDoubleClicked: { - root.selectedIcon = modelData - root.iconSelected(root.selectedIcon) - root.close() + root.selectedIcon = modelData; + root.iconSelected(root.selectedIcon); + root.close(); } } @@ -159,8 +159,8 @@ Popup { icon: "check" enabled: root.selectedIcon !== "" onClicked: { - root.iconSelected(root.selectedIcon) - root.close() + root.iconSelected(root.selectedIcon); + root.close(); } } } diff --git a/Widgets/NImageCached.qml b/Widgets/NImageCached.qml index 77aa3105..8f5a764a 100644 --- a/Widgets/NImageCached.qml +++ b/Widgets/NImageCached.qml @@ -3,8 +3,8 @@ pragma ComponentBehavior import QtQuick import Quickshell import Quickshell.Io -import qs.Commons import "../Helpers/sha256.js" as Checksum +import qs.Commons Image { id: root @@ -22,31 +22,31 @@ Image { smooth: true onImagePathChanged: { if (imagePath) { - imageHash = Checksum.sha256(imagePath) + imageHash = Checksum.sha256(imagePath); // Logger.i("NImageCached", imagePath, imageHash) } else { - source = "" - imageHash = "" + source = ""; + imageHash = ""; } } onCachePathChanged: { if (imageHash && cachePath) { // Try to load the cached version, failure will be detected below in onStatusChanged // Failure is expected and warnings are ok in the console. Don't try to improve without consulting. - source = cachePath + source = cachePath; } } onStatusChanged: { if (source == cachePath && status === Image.Error) { // Cached image was not available, show the original - source = imagePath + source = imagePath; } else if (source == imagePath && status === Image.Ready && imageHash && cachePath) { // Original image is shown and fully loaded, time to cache it - const grabPath = cachePath + const grabPath = cachePath; if (visible && width > 0 && height > 0 && Window.window && Window.window.visible) grabToImage(res => { - return res.saveToFile(grabPath) - }) + return res.saveToFile(grabPath); + }); } } } diff --git a/Widgets/NInputAction.qml b/Widgets/NInputAction.qml index 6fac9618..55cda052 100644 --- a/Widgets/NInputAction.qml +++ b/Widgets/NInputAction.qml @@ -30,8 +30,8 @@ RowLayout { placeholderText: root.placeholderText text: root.text onEditingFinished: { - root.text = text - root.editingFinished() + root.text = text; + root.editingFinished(); } Layout.fillWidth: true } @@ -48,7 +48,7 @@ RowLayout { enabled: root.actionButtonEnabled onClicked: { - root.actionClicked() + root.actionClicked(); } } } diff --git a/Widgets/NListView.qml b/Widgets/NListView.qml index 1c2b6321..a588d4fa 100644 --- a/Widgets/NListView.qml +++ b/Widgets/NListView.qml @@ -16,8 +16,8 @@ Item { property int horizontalPolicy: ScrollBar.AlwaysOff readonly property bool verticalScrollBarActive: { if (listView.ScrollBar.vertical.policy === ScrollBar.AlwaysOff) - return false - return listView.contentHeight > listView.height + return false; + return listView.contentHeight > listView.height; } readonly property real scrollBarWidth: verticalScrollBarActive ? handleWidth : 0 @@ -62,47 +62,47 @@ Item { // Forward ListView methods function positionViewAtIndex(index, mode) { - listView.positionViewAtIndex(index, mode) + listView.positionViewAtIndex(index, mode); } function positionViewAtBeginning() { - listView.positionViewAtBeginning() + listView.positionViewAtBeginning(); } function positionViewAtEnd() { - listView.positionViewAtEnd() + listView.positionViewAtEnd(); } function forceLayout() { - listView.forceLayout() + listView.forceLayout(); } function cancelFlick() { - listView.cancelFlick() + listView.cancelFlick(); } function flick(xVelocity, yVelocity) { - listView.flick(xVelocity, yVelocity) + listView.flick(xVelocity, yVelocity); } function incrementCurrentIndex() { - listView.incrementCurrentIndex() + listView.incrementCurrentIndex(); } function decrementCurrentIndex() { - listView.decrementCurrentIndex() + listView.decrementCurrentIndex(); } function indexAt(x, y) { - return listView.indexAt(x, y) + return listView.indexAt(x, y); } function itemAt(x, y) { - return listView.itemAt(x, y) + return listView.itemAt(x, y); } function itemAtIndex(index) { - return listView.itemAtIndex(index) + return listView.itemAtIndex(index); } // Set reasonable implicit sizes for Layout usage diff --git a/Widgets/NReorderCheckboxes.qml b/Widgets/NReorderCheckboxes.qml index 078c5e7a..8cd52944 100644 --- a/Widgets/NReorderCheckboxes.qml +++ b/Widgets/NReorderCheckboxes.qml @@ -24,37 +24,36 @@ Item { function toggleItem(index) { if (index < 0 || index >= root.model.length) - return - - var item = root.model[index] + return; + var item = root.model[index]; if (item.required) - return + return; // Create a new array to trigger binding update - var newModel = root.model.slice() + var newModel = root.model.slice(); newModel[index] = Object.assign({}, item, { "enabled": !item.enabled - }) - root.model = newModel + }); + root.model = newModel; - root.itemToggled(index, newModel[index].enabled) + root.itemToggled(index, newModel[index].enabled); } function moveItem(fromIndex, toIndex) { if (fromIndex === toIndex) - return + return; if (fromIndex < 0 || fromIndex >= root.model.length) - return + return; if (toIndex < 0 || toIndex >= root.model.length) - return + return; // Create a new array with item moved - var newModel = root.model.slice() - var item = newModel.splice(fromIndex, 1)[0] - newModel.splice(toIndex, 0, item) - root.model = newModel + var newModel = root.model.slice(); + var item = newModel.splice(fromIndex, 1)[0]; + newModel.splice(toIndex, 0, item); + root.model = newModel; - root.itemsReordered(fromIndex, toIndex) + root.itemsReordered(fromIndex, toIndex); } ListView { @@ -134,61 +133,61 @@ Item { onPressed: mouse => { if (delegateItem.required || delegateItem.isDisabled) { - return + return; } - delegateItem.dragStartIndex = delegateItem.index - delegateItem.dragTargetIndex = delegateItem.index - delegateItem.dragStartY = delegateItem.y - delegateItem.dragging = true - delegateItem.z = 999 + delegateItem.dragStartIndex = delegateItem.index; + delegateItem.dragTargetIndex = delegateItem.index; + delegateItem.dragStartY = delegateItem.y; + delegateItem.dragging = true; + delegateItem.z = 999; // Signal that interaction started (prevents panel close) - preventStealing = true - root.dragPotentialStarted() + preventStealing = true; + root.dragPotentialStarted(); } onPositionChanged: mouse => { if (delegateItem.dragging) { - var dy = mouse.y - dragHandle.height / 2 - var newY = delegateItem.y + dy + var dy = mouse.y - dragHandle.height / 2; + var newY = delegateItem.y + dy; // Constrain within bounds - newY = Math.max(0, Math.min(newY, listView.contentHeight - delegateItem.height)) - delegateItem.y = newY + newY = Math.max(0, Math.min(newY, listView.contentHeight - delegateItem.height)); + delegateItem.y = newY; // Calculate target index (but don't apply yet) - var targetIndex = Math.floor((newY + delegateItem.height / 2) / (delegateItem.height + delegateItem.itemSpacing)) - targetIndex = Math.max(0, Math.min(targetIndex, listView.count - 1)) + var targetIndex = Math.floor((newY + delegateItem.height / 2) / (delegateItem.height + delegateItem.itemSpacing)); + targetIndex = Math.max(0, Math.min(targetIndex, listView.count - 1)); - delegateItem.dragTargetIndex = targetIndex + delegateItem.dragTargetIndex = targetIndex; } } onReleased: { // Always signal end of interaction - preventStealing = false - root.dragPotentialEnded() + preventStealing = false; + root.dragPotentialEnded(); // Apply the model change now that drag is complete if (delegateItem.dragStartIndex !== -1 && delegateItem.dragTargetIndex !== -1 && delegateItem.dragStartIndex !== delegateItem.dragTargetIndex) { - root.moveItem(delegateItem.dragStartIndex, delegateItem.dragTargetIndex) + root.moveItem(delegateItem.dragStartIndex, delegateItem.dragTargetIndex); } - delegateItem.dragging = false - delegateItem.dragStartIndex = -1 - delegateItem.dragTargetIndex = -1 - delegateItem.z = 0 + delegateItem.dragging = false; + delegateItem.dragStartIndex = -1; + delegateItem.dragTargetIndex = -1; + delegateItem.z = 0; } onCanceled: { // Handle cancel (e.g., ESC key pressed during drag) - preventStealing = false - root.dragPotentialEnded() + preventStealing = false; + root.dragPotentialEnded(); - delegateItem.dragging = false - delegateItem.dragStartIndex = -1 - delegateItem.dragTargetIndex = -1 - delegateItem.z = 0 + delegateItem.dragging = false; + delegateItem.dragStartIndex = -1; + delegateItem.dragTargetIndex = -1; + delegateItem.z = 0; } } } @@ -233,7 +232,7 @@ Item { onClicked: { if (!delegateItem.required && !delegateItem.isDisabled) { - root.toggleItem(delegateItem.index) + root.toggleItem(delegateItem.index); } } } @@ -260,39 +259,39 @@ Item { // Position binding for non-dragging state y: { if (delegateItem.dragging) { - return delegateItem.y + return delegateItem.y; } // Check if any item is being dragged - var draggedIndex = -1 - var targetIndex = -1 + var draggedIndex = -1; + var targetIndex = -1; for (var i = 0; i < listView.count; i++) { - var item = listView.itemAtIndex(i) + var item = listView.itemAtIndex(i); if (item && item.dragging) { - draggedIndex = item.dragStartIndex - targetIndex = item.dragTargetIndex - break + draggedIndex = item.dragStartIndex; + targetIndex = item.dragTargetIndex; + break; } } // If an item is being dragged, adjust positions if (draggedIndex !== -1 && targetIndex !== -1 && draggedIndex !== targetIndex) { - var currentIndex = delegateItem.index + var currentIndex = delegateItem.index; if (draggedIndex < targetIndex) { // Dragging down: shift items up between draggedIndex and targetIndex if (currentIndex > draggedIndex && currentIndex <= targetIndex) { - return (currentIndex - 1) * (delegateItem.height + delegateItem.itemSpacing) + return (currentIndex - 1) * (delegateItem.height + delegateItem.itemSpacing); } } else { // Dragging up: shift items down between targetIndex and draggedIndex if (currentIndex >= targetIndex && currentIndex < draggedIndex) { - return (currentIndex + 1) * (delegateItem.height + delegateItem.itemSpacing) + return (currentIndex + 1) * (delegateItem.height + delegateItem.itemSpacing); } } } - return delegateItem.index * (delegateItem.height + delegateItem.itemSpacing) + return delegateItem.index * (delegateItem.height + delegateItem.itemSpacing); } Behavior on y { diff --git a/Widgets/NScrollView.qml b/Widgets/NScrollView.qml index 0352492b..b3699afe 100644 --- a/Widgets/NScrollView.qml +++ b/Widgets/NScrollView.qml @@ -23,33 +23,33 @@ T.ScrollView { // Configure the internal flickable when it becomes available Component.onCompleted: { - configureFlickable() + configureFlickable(); } // Function to configure the underlying Flickable function configureFlickable() { // Find the internal Flickable (it's usually the first child) for (var i = 0; i < children.length; i++) { - var child = children[i] + var child = children[i]; if (child.toString().indexOf("Flickable") !== -1) { // Configure the flickable to prevent horizontal scrolling - child.boundsBehavior = root.boundsBehavior + child.boundsBehavior = root.boundsBehavior; if (root.preventHorizontalScroll) { - child.flickableDirection = Flickable.VerticalFlick - child.contentWidth = Qt.binding(() => child.width) + child.flickableDirection = Flickable.VerticalFlick; + child.contentWidth = Qt.binding(() => child.width); } else { - child.flickableDirection = root.flickableDirection + child.flickableDirection = root.flickableDirection; } - break + break; } } } // Watch for changes in horizontalPolicy onHorizontalPolicyChanged: { - preventHorizontalScroll = (horizontalPolicy === ScrollBar.AlwaysOff) - configureFlickable() + preventHorizontalScroll = (horizontalPolicy === ScrollBar.AlwaysOff); + configureFlickable(); } ScrollBar.vertical: ScrollBar { diff --git a/Widgets/NSearchableComboBox.qml b/Widgets/NSearchableComboBox.qml index bd334124..4dac05d3 100644 --- a/Widgets/NSearchableComboBox.qml +++ b/Widgets/NSearchableComboBox.qml @@ -1,9 +1,9 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import "../Helpers/FuzzySort.js" as Fuzzysort import qs.Commons import qs.Widgets -import "../Helpers/FuzzySort.js" as Fuzzysort RowLayout { id: root @@ -13,9 +13,7 @@ RowLayout { property string label: "" property string description: "" - property ListModel model: { - - } + property ListModel model: {} property string currentKey: "" property string placeholder: "" property string searchPlaceholder: I18n.tr("placeholders.search") @@ -35,39 +33,39 @@ RowLayout { function findIndexByKey(key) { for (var i = 0; i < root.model.count; i++) { if (root.model.get(i).key === key) { - return i + return i; } } - return -1 + return -1; } function findIndexByKeyInFiltered(key) { for (var i = 0; i < root.filteredModel.count; i++) { if (root.filteredModel.get(i).key === key) { - return i + return i; } } - return -1 + return -1; } function filterModel() { - filteredModel.clear() + filteredModel.clear(); // Check if model exists and has items if (!root.model || root.model.count === undefined || root.model.count === 0) { - return + return; } if (searchText.trim() === "") { // If no search text, show all items for (var i = 0; i < root.model.count; i++) { - filteredModel.append(root.model.get(i)) + filteredModel.append(root.model.get(i)); } } else { // Convert ListModel to array for fuzzy search - var items = [] + var items = []; for (var i = 0; i < root.model.count; i++) { - items.push(root.model.get(i)) + items.push(root.model.get(i)); } // Use fuzzy search if available, fallback to simple search @@ -76,19 +74,19 @@ RowLayout { "key": "name", "threshold": -1000, "limit": 50 - }) + }); // Add results in order of relevance for (var j = 0; j < fuzzyResults.length; j++) { - filteredModel.append(fuzzyResults[j].obj) + filteredModel.append(fuzzyResults[j].obj); } } else { // Fallback to simple search - var searchLower = searchText.toLowerCase() + var searchLower = searchText.toLowerCase(); for (var i = 0; i < items.length; i++) { - var item = items[i] + var item = items[i]; if (item.name.toLowerCase().includes(searchLower)) { - filteredModel.append(item) + filteredModel.append(item); } } } @@ -116,7 +114,7 @@ RowLayout { currentIndex: findIndexByKeyInFiltered(currentKey) onActivated: { if (combo.currentIndex >= 0 && combo.currentIndex < filteredModel.count) { - root.selected(filteredModel.get(combo.currentIndex).key) + root.selected(filteredModel.get(combo.currentIndex).key); } } @@ -192,14 +190,14 @@ RowLayout { onHoveredChanged: { if (hovered) { - ListView.view.currentIndex = index + ListView.view.currentIndex = index; } } onClicked: { - root.selected(filteredModel.get(index).key) - combo.currentIndex = root.findIndexByKeyInFiltered(filteredModel.get(index).key) - combo.popup.close() + root.selected(filteredModel.get(index).key); + combo.currentIndex = root.findIndexByKeyInFiltered(filteredModel.get(index).key); + combo.popup.close(); } contentItem: RowLayout { @@ -269,7 +267,7 @@ RowLayout { Connections { target: root function onCurrentKeyChanged() { - combo.currentIndex = root.findIndexByKeyInFiltered(currentKey) + combo.currentIndex = root.findIndexByKeyInFiltered(currentKey); } } @@ -279,13 +277,13 @@ RowLayout { function onVisibleChanged() { if (combo.popup.visible) { // Ensure the model is filtered when popup opens - filterModel() + filterModel(); // Small delay to ensure the popup is fully rendered Qt.callLater(() => { if (searchInput && searchInput.inputItem) { - searchInput.inputItem.forceActiveFocus() + searchInput.inputItem.forceActiveFocus(); } - }) + }); } } } diff --git a/Widgets/NSectionEditor.qml b/Widgets/NSectionEditor.qml index a2ecbedf..06098b85 100644 --- a/Widgets/NSectionEditor.qml +++ b/Widgets/NSectionEditor.qml @@ -33,45 +33,45 @@ NBox { Layout.fillWidth: true Layout.minimumHeight: { // header + minimal content area - var absoluteMin = (Style.marginL * 2) + (Style.fontSizeL * 2) + Style.marginM + (65 * Style.uiScaleRatio) + var absoluteMin = (Style.marginL * 2) + (Style.fontSizeL * 2) + Style.marginM + (65 * Style.uiScaleRatio); - var widgetCount = widgetModel.length + var widgetCount = widgetModel.length; if (widgetCount === 0) { - return absoluteMin + return absoluteMin; } // Calculate rows based on estimated widget layout - var availableWidth = parent.width - (Style.marginL * 2) - var avgWidgetWidth = 120 * Style.uiScaleRatio // More accurate estimate - var widgetsPerRow = Math.max(1, Math.floor(availableWidth / avgWidgetWidth)) - var rows = Math.ceil(widgetCount / widgetsPerRow) + var availableWidth = parent.width - (Style.marginL * 2); + var avgWidgetWidth = 120 * Style.uiScaleRatio; // More accurate estimate + var widgetsPerRow = Math.max(1, Math.floor(availableWidth / avgWidgetWidth)); + var rows = Math.ceil(widgetCount / widgetsPerRow); // Header height + spacing + (rows * widget height) + (spacing between rows) + margins - var headerHeight = Style.fontSizeL * 2 - var widgetHeight = Style.baseWidgetSize * 1.15 * Style.uiScaleRatio - var widgetAreaHeight = ((rows + 1) * widgetHeight) + ((rows - 1) * Style.marginS) + var headerHeight = Style.fontSizeL * 2; + var widgetHeight = Style.baseWidgetSize * 1.15 * Style.uiScaleRatio; + var widgetAreaHeight = ((rows + 1) * widgetHeight) + ((rows - 1) * Style.marginS); - return Math.max(absoluteMin, (Style.marginL * 2) + headerHeight + Style.marginM + widgetAreaHeight) + return Math.max(absoluteMin, (Style.marginL * 2) + headerHeight + Style.marginM + widgetAreaHeight); } // Generate widget color from name checksum function getWidgetColor(widget) { const totalSum = JSON.stringify(widget).split('').reduce((acc, character) => { - return acc + character.charCodeAt(0) - }, 0) + return acc + character.charCodeAt(0); + }, 0); switch (totalSum % 6) { case 0: - return [Color.mPrimary, Color.mOnPrimary] + return [Color.mPrimary, Color.mOnPrimary]; case 1: - return [Color.mSecondary, Color.mOnSecondary] + return [Color.mSecondary, Color.mOnSecondary]; case 2: - return [Color.mTertiary, Color.mOnTertiary] + return [Color.mTertiary, Color.mOnTertiary]; case 3: - return [Color.mError, Color.mOnError] + return [Color.mError, Color.mOnError]; case 4: - return [Color.mOnSurface, Color.mSurface] + return [Color.mOnSurface, Color.mSurface]; case 5: - return [Color.mOnSurfaceVariant, Color.mSurfaceVariant] + return [Color.mOnSurfaceVariant, Color.mSurfaceVariant]; } } @@ -124,9 +124,9 @@ NBox { target: availableWidgets function onCountChanged() { // Trigger a re-filter by clearing and re-setting the search text - var currentSearch = comboBox.searchText - comboBox.searchText = "" - comboBox.searchText = currentSearch + var currentSearch = comboBox.searchText; + comboBox.searchText = ""; + comboBox.searchText = currentSearch; } } } @@ -143,8 +143,8 @@ NBox { Layout.leftMargin: Style.marginS onClicked: { if (comboBox.currentKey !== "" && !root.isAtMaxCapacity) { - addWidget(comboBox.currentKey, sectionId) - comboBox.currentKey = "" + addWidget(comboBox.currentKey, sectionId); + comboBox.currentKey = ""; } } } @@ -204,22 +204,26 @@ NBox { id: contextMenu parent: Overlay.overlay width: 240 * Style.uiScaleRatio - model: [{ + model: [ + { "label": I18n.tr("tooltips.move-to-left-section"), "action": "left", "icon": "arrow-bar-to-left", "visible": root.availableSections.includes("left") && root.sectionId !== "left" - }, { + }, + { "label": I18n.tr("tooltips.move-to-center-section"), "action": "center", "icon": "layout-columns", "visible": root.availableSections.includes("center") && root.sectionId !== "center" - }, { + }, + { "label": I18n.tr("tooltips.move-to-right-section"), "action": "right", "icon": "arrow-bar-to-right", "visible": root.availableSections.includes("right") && root.sectionId !== "right" - }] + } + ] onTriggered: action => root.moveWidget(root.sectionId, index, action) } @@ -235,10 +239,10 @@ NBox { onPressed: mouse => { if (mouse.button === Qt.RightButton) { // Check if click is not on the buttons area - const localX = mouse.x - const buttonsStartX = parent.width - (parent.buttonsCount * parent.buttonsWidth) + const localX = mouse.x; + const buttonsStartX = parent.width - (parent.buttonsCount * parent.buttonsWidth); if (localX < buttonsStartX) { - contextMenu.openAtItem(widgetItem, mouse.x, mouse.y) + contextMenu.openAtItem(widgetItem, mouse.x, mouse.y); } } } @@ -273,33 +277,33 @@ NBox { colorBgHover: Qt.alpha(Color.mOnPrimary, Style.opacityLight) colorFgHover: Color.mOnPrimary onClicked: { - var component = Qt.createComponent(Qt.resolvedUrl(root.settingsDialogComponent)) + var component = Qt.createComponent(Qt.resolvedUrl(root.settingsDialogComponent)); function instantiateAndOpen() { var dialog = component.createObject(Overlay.overlay, { "widgetIndex": index, "widgetData": modelData, "widgetId": modelData.id, "sectionId": root.sectionId - }) + }); if (dialog) { - dialog.updateWidgetSettings.connect(root.updateWidgetSettings) - dialog.open() + dialog.updateWidgetSettings.connect(root.updateWidgetSettings); + dialog.open(); } else { - Logger.e("NSectionEditor", "Failed to create settings dialog instance") + Logger.e("NSectionEditor", "Failed to create settings dialog instance"); } } if (component.status === Component.Ready) { - instantiateAndOpen() + instantiateAndOpen(); } else if (component.status === Component.Error) { - Logger.e("NSectionEditor", component.errorString()) + Logger.e("NSectionEditor", component.errorString()); } else { component.statusChanged.connect(function () { if (component.status === Component.Ready) { - instantiateAndOpen() + instantiateAndOpen(); } else if (component.status === Component.Error) { - Logger.e("NSectionEditor", component.errorString()) + Logger.e("NSectionEditor", component.errorString()); } - }) + }); } } } @@ -315,7 +319,7 @@ NBox { colorBgHover: Qt.alpha(Color.mOnPrimary, Style.opacityLight) colorFgHover: Color.mOnPrimary onClicked: { - removeWidget(sectionId, index) + removeWidget(sectionId, index); } } } @@ -410,52 +414,51 @@ NBox { // Drop position calculation function updateDropIndicator(mouseX, mouseY) { if (!dragStarted || draggedIndex === -1) { - dropIndicator.opacity = 0 - pulseAnimation.running = false - return + dropIndicator.opacity = 0; + pulseAnimation.running = false; + return; } - let bestIndex = -1 - let bestPosition = null - let minDistance = Infinity + let bestIndex = -1; + let bestPosition = null; + let minDistance = Infinity; // Check position relative to each widget for (var i = 0; i < widgetModel.length; i++) { if (i === draggedIndex) - continue - - const widget = widgetFlow.children[i] + continue; + const widget = widgetFlow.children[i]; if (!widget || widget.widgetIndex === undefined) - continue + continue; // Check distance to left edge (insert before) - const leftDist = Math.sqrt(Math.pow(mouseX - widget.x, 2) + Math.pow(mouseY - (widget.y + widget.height / 2), 2)) + const leftDist = Math.sqrt(Math.pow(mouseX - widget.x, 2) + Math.pow(mouseY - (widget.y + widget.height / 2), 2)); // Check distance to right edge (insert after) - const rightDist = Math.sqrt(Math.pow(mouseX - (widget.x + widget.width), 2) + Math.pow(mouseY - (widget.y + widget.height / 2), 2)) + const rightDist = Math.sqrt(Math.pow(mouseX - (widget.x + widget.width), 2) + Math.pow(mouseY - (widget.y + widget.height / 2), 2)); if (leftDist < minDistance) { - minDistance = leftDist - bestIndex = i - bestPosition = Qt.point(widget.x - dropIndicator.width / 2 - Style.marginXS, widget.y) + minDistance = leftDist; + bestIndex = i; + bestPosition = Qt.point(widget.x - dropIndicator.width / 2 - Style.marginXS, widget.y); } if (rightDist < minDistance) { - minDistance = rightDist - bestIndex = i + 1 - bestPosition = Qt.point(widget.x + widget.width + Style.marginXS - dropIndicator.width / 2, widget.y) + minDistance = rightDist; + bestIndex = i + 1; + bestPosition = Qt.point(widget.x + widget.width + Style.marginXS - dropIndicator.width / 2, widget.y); } } // Check if we should insert at position 0 (very beginning) if (widgetModel.length > 0 && draggedIndex !== 0) { - const firstWidget = widgetFlow.children[0] + const firstWidget = widgetFlow.children[0]; if (firstWidget) { - const dist = Math.sqrt(Math.pow(mouseX, 2) + Math.pow(mouseY - firstWidget.y, 2)) + const dist = Math.sqrt(Math.pow(mouseX, 2) + Math.pow(mouseY - firstWidget.y, 2)); if (dist < minDistance && mouseX < firstWidget.x + firstWidget.width / 2) { - minDistance = dist - bestIndex = 0 - bestPosition = Qt.point(Math.max(0, firstWidget.x - dropIndicator.width - Style.marginS), firstWidget.y) + minDistance = dist; + bestIndex = 0; + bestPosition = Qt.point(Math.max(0, firstWidget.x - dropIndicator.width - Style.marginS), firstWidget.y); } } } @@ -463,68 +466,67 @@ NBox { // Only show indicator if we're close enough and it's a different position if (minDistance < 80 && bestIndex !== -1) { // Adjust index if we're moving forward - let adjustedIndex = bestIndex + let adjustedIndex = bestIndex; if (bestIndex > draggedIndex) { - adjustedIndex = bestIndex - 1 + adjustedIndex = bestIndex - 1; } // Don't show if it's the same position if (adjustedIndex === draggedIndex) { - dropIndicator.opacity = 0 - pulseAnimation.running = false - dropTargetIndex = -1 - return + dropIndicator.opacity = 0; + pulseAnimation.running = false; + dropTargetIndex = -1; + return; } - dropTargetIndex = adjustedIndex + dropTargetIndex = adjustedIndex; if (bestPosition) { - dropIndicator.x = bestPosition.x - dropIndicator.y = bestPosition.y - dropIndicator.opacity = 1 + dropIndicator.x = bestPosition.x; + dropIndicator.y = bestPosition.y; + dropIndicator.opacity = 1; if (!pulseAnimation.running) { - pulseAnimation.running = true + pulseAnimation.running = true; } } } else { - dropIndicator.opacity = 0 - pulseAnimation.running = false - dropTargetIndex = -1 + dropIndicator.opacity = 0; + pulseAnimation.running = false; + dropTargetIndex = -1; } } onPressed: mouse => { - startPos = Qt.point(mouse.x, mouse.y) - dragStarted = false - potentialDrag = false - draggedIndex = -1 - draggedWidget = null - dropTargetIndex = -1 - draggedModelData = null + startPos = Qt.point(mouse.x, mouse.y); + dragStarted = false; + potentialDrag = false; + draggedIndex = -1; + draggedWidget = null; + dropTargetIndex = -1; + draggedModelData = null; // Find which widget was clicked for (var i = 0; i < widgetModel.length; i++) { - const widget = widgetFlow.children[i] + const widget = widgetFlow.children[i]; if (widget && widget.widgetIndex !== undefined) { if (mouse.x >= widget.x && mouse.x <= widget.x + widget.width && mouse.y >= widget.y && mouse.y <= widget.y + widget.height) { - - const localX = mouse.x - widget.x - const buttonsStartX = widget.width - (widget.buttonsCount * widget.buttonsWidth) + const localX = mouse.x - widget.x; + const buttonsStartX = widget.width - (widget.buttonsCount * widget.buttonsWidth); if (localX < buttonsStartX) { // This is a draggable area - prevent panel close immediately - draggedIndex = widget.widgetIndex - draggedWidget = widget - draggedModelData = widget.modelData - potentialDrag = true - preventStealing = true + draggedIndex = widget.widgetIndex; + draggedWidget = widget; + draggedModelData = widget.modelData; + potentialDrag = true; + preventStealing = true; // Signal that interaction started (prevents panel close) - root.dragPotentialStarted() - break + root.dragPotentialStarted(); + break; } else { // This is a button area - let the click through - mouse.accepted = false - return + mouse.accepted = false; + return; } } } @@ -533,28 +535,28 @@ NBox { onPositionChanged: mouse => { if (draggedIndex !== -1 && potentialDrag) { - const deltaX = mouse.x - startPos.x - const deltaY = mouse.y - startPos.y - const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY) + const deltaX = mouse.x - startPos.x; + const deltaY = mouse.y - startPos.y; + const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (!dragStarted && distance > dragThreshold) { - dragStarted = true + dragStarted = true; // Setup ghost widget if (draggedWidget) { - dragGhost.width = draggedWidget.width - dragGhost.color = root.getWidgetColor(draggedModelData)[0] - ghostText.text = draggedModelData.id + dragGhost.width = draggedWidget.width; + dragGhost.color = root.getWidgetColor(draggedModelData)[0]; + ghostText.text = draggedModelData.id; } } if (dragStarted) { // Move ghost widget - dragGhost.x = mouse.x - dragGhost.width / 2 - dragGhost.y = mouse.y - dragGhost.height / 2 + dragGhost.x = mouse.x - dragGhost.width / 2; + dragGhost.y = mouse.y - dragGhost.height / 2; // Update drop indicator - updateDropIndicator(mouse.x, mouse.y) + updateDropIndicator(mouse.x, mouse.y); } } } @@ -562,52 +564,52 @@ NBox { onReleased: mouse => { if (dragStarted && dropTargetIndex !== -1 && dropTargetIndex !== draggedIndex) { // Perform the reorder - reorderWidget(sectionId, draggedIndex, dropTargetIndex) + reorderWidget(sectionId, draggedIndex, dropTargetIndex); } // Always signal end of interaction if we started one if (potentialDrag) { - root.dragPotentialEnded() + root.dragPotentialEnded(); } // Reset everything - dragStarted = false - potentialDrag = false - draggedIndex = -1 - draggedWidget = null - dropTargetIndex = -1 - draggedModelData = null - preventStealing = false - dropIndicator.opacity = 0 - pulseAnimation.running = false - dragGhost.width = 0 + dragStarted = false; + potentialDrag = false; + draggedIndex = -1; + draggedWidget = null; + dropTargetIndex = -1; + draggedModelData = null; + preventStealing = false; + dropIndicator.opacity = 0; + pulseAnimation.running = false; + dragGhost.width = 0; } onExited: { if (dragStarted) { // Hide drop indicator when mouse leaves, but keep ghost visible - dropIndicator.opacity = 0 - pulseAnimation.running = false + dropIndicator.opacity = 0; + pulseAnimation.running = false; } } onCanceled: { // Handle cancel (e.g., ESC key pressed during drag) if (potentialDrag) { - root.dragPotentialEnded() + root.dragPotentialEnded(); } // Reset everything - dragStarted = false - potentialDrag = false - draggedIndex = -1 - draggedWidget = null - dropTargetIndex = -1 - draggedModelData = null - preventStealing = false - dropIndicator.opacity = 0 - pulseAnimation.running = false - dragGhost.width = 0 + dragStarted = false; + potentialDrag = false; + draggedIndex = -1; + draggedWidget = null; + dropTargetIndex = -1; + draggedModelData = null; + preventStealing = false; + dropIndicator.opacity = 0; + pulseAnimation.running = false; + dragGhost.width = 0; } } } diff --git a/Widgets/NSlider.qml b/Widgets/NSlider.qml index 793dd7bf..2c2d7b4a 100644 --- a/Widgets/NSlider.qml +++ b/Widgets/NSlider.qml @@ -115,16 +115,16 @@ Slider { propagateComposedEvents: true onEntered: { - root.hovering = true + root.hovering = true; if (root.tooltipText) { - TooltipService.show(Screen, knob, root.tooltipText, root.tooltipDirection) + TooltipService.show(Screen, knob, root.tooltipText, root.tooltipDirection); } } onExited: { - root.hovering = false + root.hovering = false; if (root.tooltipText) { - TooltipService.hide() + TooltipService.hide(); } } } @@ -134,7 +134,7 @@ Slider { target: root function onPressedChanged() { if (root.pressed && root.tooltipText) { - TooltipService.hide() + TooltipService.hide(); } } } diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index 0b96cfc4..0b15e726 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -56,20 +56,20 @@ RowLayout { acceptedButtons: Qt.NoButton hoverEnabled: true onEntered: { - root.hovering = true - root.entered() + root.hovering = true; + root.entered(); } onExited: { - root.hovering = false - root.exited() + root.hovering = false; + root.exited(); } onWheel: wheel => { if (wheel.angleDelta.y > 0 && root.value < root.to) { - let newValue = Math.min(root.to, root.value + root.stepSize) - root.value = newValue + let newValue = Math.min(root.to, root.value + root.stepSize); + root.value = newValue; } else if (wheel.angleDelta.y < 0 && root.value > root.from) { - let newValue = Math.max(root.from, root.value - root.stepSize) - root.value = newValue + let newValue = Math.max(root.from, root.value - root.stepSize); + root.value = newValue; } } } @@ -163,8 +163,8 @@ RowLayout { cursorShape: Qt.PointingHandCursor enabled: root.enabled && root.value > root.from onClicked: { - let newValue = Math.max(root.from, root.value - root.stepSize) - root.value = newValue + let newValue = Math.max(root.from, root.value - root.stepSize); + root.value = newValue; } } } @@ -258,8 +258,8 @@ RowLayout { cursorShape: Qt.PointingHandCursor enabled: root.enabled && root.value < root.to onClicked: { - let newValue = Math.min(root.to, root.value + root.stepSize) - root.value = newValue + let newValue = Math.min(root.to, root.value + root.stepSize); + root.value = newValue; } } } @@ -310,29 +310,29 @@ RowLayout { } Keys.onReturnPressed: { - applyValue() - focus = false + applyValue(); + focus = false; } Keys.onEscapePressed: { - text = root.value.toString() - focus = false + text = root.value.toString(); + focus = false; } onFocusChanged: { if (focus) { - selectAll() + selectAll(); } else { - applyValue() + applyValue(); } } function applyValue() { - let newValue = parseInt(text) + let newValue = parseInt(text); if (!isNaN(newValue)) { // Don't manually set text here - let the binding handle it - newValue = Math.max(root.from, Math.min(root.to, newValue)) - root.value = newValue + newValue = Math.max(root.from, Math.min(root.to, newValue)); + root.value = newValue; } } } diff --git a/Widgets/NTabButton.qml b/Widgets/NTabButton.qml index a1def44b..d753d800 100644 --- a/Widgets/NTabButton.qml +++ b/Widgets/NTabButton.qml @@ -57,10 +57,10 @@ Rectangle { onEntered: root.isHovered = true onExited: root.isHovered = false onClicked: { - root.clicked() + root.clicked(); // Update parent NTabBar's currentIndex if (root.parent && root.parent.parent && root.parent.parent.currentIndex !== undefined) { - root.parent.parent.currentIndex = root.tabIndex + root.parent.parent.currentIndex = root.tabIndex; } } } diff --git a/Widgets/NText.qml b/Widgets/NText.qml index 57c20ed0..3dd3933f 100644 --- a/Widgets/NText.qml +++ b/Widgets/NText.qml @@ -10,11 +10,11 @@ Text { property real pointSize: Style.fontSizeM property bool applyUiScale: true property real fontScale: { - const fontScale = (root.family === Settings.data.ui.fontDefault ? Settings.data.ui.fontDefaultScale : Settings.data.ui.fontFixedScale) + const fontScale = (root.family === Settings.data.ui.fontDefault ? Settings.data.ui.fontDefaultScale : Settings.data.ui.fontFixedScale); if (applyUiScale) { - return fontScale * Style.uiScaleRatio + return fontScale * Style.uiScaleRatio; } - return fontScale + return fontScale; } font.family: root.family diff --git a/Widgets/NTextInput.qml b/Widgets/NTextInput.qml index b2a5e0ea..8694768f 100644 --- a/Widgets/NTextInput.qml +++ b/Widgets/NTextInput.qml @@ -74,30 +74,30 @@ ColumnLayout { propagateComposedEvents: false onPressed: mouse => { - mouse.accepted = true + mouse.accepted = true; // Focus the input and position cursor - input.forceActiveFocus() - var inputPos = mapToItem(inputContainer, mouse.x, mouse.y) + input.forceActiveFocus(); + var inputPos = mapToItem(inputContainer, mouse.x, mouse.y); if (inputPos.x >= 0 && inputPos.x <= inputContainer.width) { - var textPos = inputPos.x - Style.marginM + var textPos = inputPos.x - Style.marginM; if (textPos >= 0 && textPos <= input.width) { - input.cursorPosition = input.positionAt(textPos, input.height / 2) + input.cursorPosition = input.positionAt(textPos, input.height / 2); } } } onReleased: mouse => { - mouse.accepted = true + mouse.accepted = true; } onDoubleClicked: mouse => { - mouse.accepted = true - input.selectAll() + mouse.accepted = true; + input.selectAll(); } onPositionChanged: mouse => { - mouse.accepted = true + mouse.accepted = true; } onWheel: wheel => { - wheel.accepted = true + wheel.accepted = true; } } @@ -166,31 +166,31 @@ ColumnLayout { property int selectionStart: 0 onPressed: mouse => { - mouse.accepted = true - input.forceActiveFocus() - var pos = input.positionAt(mouse.x, mouse.y) - input.cursorPosition = pos - selectionStart = pos + mouse.accepted = true; + input.forceActiveFocus(); + var pos = input.positionAt(mouse.x, mouse.y); + input.cursorPosition = pos; + selectionStart = pos; } onPositionChanged: mouse => { if (mouse.buttons & Qt.LeftButton) { - mouse.accepted = true - var pos = input.positionAt(mouse.x, mouse.y) - input.select(selectionStart, pos) + mouse.accepted = true; + var pos = input.positionAt(mouse.x, mouse.y); + input.select(selectionStart, pos); } } onDoubleClicked: mouse => { - mouse.accepted = true - input.selectAll() + mouse.accepted = true; + input.selectAll(); } onReleased: mouse => { - mouse.accepted = true + mouse.accepted = true; } onWheel: wheel => { - wheel.accepted = true + wheel.accepted = true; } } } @@ -212,8 +212,8 @@ ColumnLayout { enabled: input.text.length > 0 && !root.readOnly onClicked: { - input.clear() - input.forceActiveFocus() + input.clear(); + input.forceActiveFocus(); } } } diff --git a/Widgets/NTextInputButton.qml b/Widgets/NTextInputButton.qml index dfda42f9..3b016077 100644 --- a/Widgets/NTextInputButton.qml +++ b/Widgets/NTextInputButton.qml @@ -1,6 +1,6 @@ import QtQuick -import QtQuick.Layouts import QtQuick.Controls +import QtQuick.Layouts import qs.Commons import qs.Widgets diff --git a/Widgets/NToggle.qml b/Widgets/NToggle.qml index abbe75fc..95e369d1 100644 --- a/Widgets/NToggle.qml +++ b/Widgets/NToggle.qml @@ -79,20 +79,20 @@ RowLayout { hoverEnabled: true onEntered: { if (!enabled) - return - hovering = true - root.entered() + return; + hovering = true; + root.entered(); } onExited: { if (!enabled) - return - hovering = false - root.exited() + return; + hovering = false; + root.exited(); } onClicked: { if (!enabled) - return - root.toggled(!root.checked) + return; + root.toggled(!root.checked); } } } diff --git a/shell.qml b/shell.qml index fee3667c..d41a0c05 100644 --- a/shell.qml +++ b/shell.qml @@ -1,9 +1,8 @@ - /* - * Noctalia – made by https://github.com/noctalia-dev - * Licensed under the MIT License. - * Forks and modifications are allowed under the MIT License, - * but proper credit must be given to the original author. +* Noctalia – made by https://github.com/noctalia-dev +* Licensed under the MIT License. +* Forks and modifications are allowed under the MIT License, +* but proper credit must be given to the original author. */ // Qt & Quickshell Core @@ -13,24 +12,24 @@ import Quickshell.Services.SystemTray // Commons & Services import qs.Commons -import qs.Services.Control -import qs.Services.Theming -import qs.Services.Hardware -import qs.Services.Location -import qs.Services.Networking -import qs.Services.Power -import qs.Services.System -import qs.Services.UI // Modules import qs.Modules.Background import qs.Modules.Bar import qs.Modules.Dock -import qs.Modules.MainScreen import qs.Modules.LockScreen +import qs.Modules.MainScreen import qs.Modules.Notification import qs.Modules.OSD import qs.Modules.Toast +import qs.Services.Control +import qs.Services.Hardware +import qs.Services.Location +import qs.Services.Networking +import qs.Services.Power +import qs.Services.System +import qs.Services.Theming +import qs.Services.UI ShellRoot { id: shellRoot @@ -39,28 +38,28 @@ ShellRoot { property bool settingsLoaded: false Component.onCompleted: { - Logger.i("Shell", "---------------------------") - Logger.i("Shell", "Noctalia Hello!") + Logger.i("Shell", "---------------------------"); + Logger.i("Shell", "Noctalia Hello!"); } Connections { target: Quickshell function onReloadCompleted() { - Quickshell.inhibitReloadPopup() + Quickshell.inhibitReloadPopup(); } } Connections { target: I18n ? I18n : null function onTranslationsLoaded() { - i18nLoaded = true + i18nLoaded = true; } } Connections { target: Settings ? Settings : null function onSettingsLoaded() { - settingsLoaded = true + settingsLoaded = true; } } Loader { @@ -68,25 +67,23 @@ ShellRoot { sourceComponent: Item { Component.onCompleted: { - Logger.i("Shell", "---------------------------") - SystemTrayService.init() - WallpaperService.init() - AppThemeService.init() - ColorSchemeService.init() - LocationService.init() - NightLightService.apply() - DarkModeService.init() - HooksService.init() - BluetoothService.init() - BatteryService.init() - IdleInhibitorService.init() - PowerProfileService.init() - HostService.init() - FontService.init() + Logger.i("Shell", "---------------------------"); + WallpaperService.init(); + AppThemeService.init(); + ColorSchemeService.init(); + LocationService.init(); + NightLightService.apply(); + DarkModeService.init(); + HooksService.init(); + BluetoothService.init(); + IdleInhibitorService.init(); + PowerProfileService.init(); + HostService.init(); + FontService.init(); // Only open the setup wizard for new users if (!Settings.data.setupCompleted) { - checkSetupWizard() + checkSetupWizard(); } } @@ -101,7 +98,7 @@ ShellRoot { id: lockScreen Component.onCompleted: { // Save a ref. to our lockScreen so we can access it easily - PanelService.lockScreen = lockScreen + PanelService.lockScreen = lockScreen; } } @@ -122,40 +119,40 @@ ShellRoot { running: false interval: 1000 onTriggered: { - showSetupWizard() + showSetupWizard(); } } function checkSetupWizard() { // Wait for distro service if (!HostService.isReady) { - Qt.callLater(checkSetupWizard) - return + Qt.callLater(checkSetupWizard); + return; } // No setup wizard on NixOS if (HostService.isNixOS) { - Settings.data.setupCompleted = true - return + Settings.data.setupCompleted = true; + return; } if (Settings.data.settingsVersion >= Settings.settingsVersion) { - setupWizardTimer.start() + setupWizardTimer.start(); } else { - Settings.data.setupCompleted = true + Settings.data.setupCompleted = true; } } function showSetupWizard() { // Open Setup Wizard as a panel in the same windowing system as Settings/ControlCenter if (Quickshell.screens.length > 0) { - var targetScreen = Quickshell.screens[0] - var setupPanel = PanelService.getPanel("setupWizardPanel", targetScreen) + var targetScreen = Quickshell.screens[0]; + var setupPanel = PanelService.getPanel("setupWizardPanel", targetScreen); if (setupPanel) { - setupPanel.open() + setupPanel.open(); } else { // If not yet loaded, ensure it loads and try again shortly - setupWizardTimer.restart() + setupWizardTimer.restart(); } } }