diff --git a/kde-display-profile-manager.py b/kde-display-profile-manager.py index c35f13d..119cb2b 100755 --- a/kde-display-profile-manager.py +++ b/kde-display-profile-manager.py @@ -5,6 +5,7 @@ import json import subprocess import sys import os +import shlex from pathlib import Path # Try to import PySide6 for the GUI @@ -206,7 +207,7 @@ class DisplayProfileManagerGUI(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("KDE Display Profile Manager") - self.setMinimumSize(400, 300) + self.setMinimumSize(420, 300) # Ensure default directory exists DEFAULT_PROFILE_DIR.mkdir(parents=True, exist_ok=True) @@ -237,6 +238,11 @@ class DisplayProfileManagerGUI(QMainWindow): self.refresh_btn.clicked.connect(self.refresh_profiles) btn_layout.addWidget(self.refresh_btn) + self.copy_btn = QPushButton("Copy Load Cmd") + self.copy_btn.setMinimumWidth(120) + self.copy_btn.clicked.connect(self.on_copy_clicked) + btn_layout.addWidget(self.copy_btn) + layout.addLayout(btn_layout) def refresh_profiles(self): @@ -291,6 +297,23 @@ class DisplayProfileManagerGUI(QMainWindow): except Exception as e: QMessageBox.critical(self, "Error", f"Failed to load profile: {e}") + def on_copy_clicked(self): + selected_item = self.profile_list.currentItem() + if not selected_item: + QMessageBox.warning(self, "No Selection", "Please select a profile to copy the command for.") + return + + profile_name = selected_item.text() + profile_path = DEFAULT_PROFILE_DIR / f"{profile_name}.json" + + script_path = os.path.abspath(__file__) + cmd = f"python3 {shlex.quote(script_path)} load {shlex.quote(str(profile_path))}" + + clipboard = QApplication.clipboard() + clipboard.setText(cmd) + + QMessageBox.information(self, "Command Copied", f"The following command has been copied to your clipboard:\n\n{cmd}") + def show_gui(): if not PYSIDE_AVAILABLE: print("Error: PySide6 is not installed. Please install it to use the GUI.", file=sys.stderr) diff --git a/load-display-profile.sh b/load-display-profile.sh deleted file mode 100755 index 8fac973..0000000 --- a/load-display-profile.sh +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env bash - -VERBOSE=1 - - -function log { - if [ $VERBOSE -eq 1 ]; then - echo "$@" - fi -} -set -e - -# Make sure a config file was provided -if [ $# -lt 1 ]; then - echo "Usage: $0 " - exit -fi - -PROFILE=$1 - -if [[ ! -f "$PROFILE" ]]; then - echo "Profile file not found: $PROFILE" >&2 - exit 1 -fi - -if ! command -v jq &>/dev/null; then - echo "jq not installed!" >&2 - exit 1 -fi - -if ! command -v kscreen-doctor &>/dev/null; then - echo "kscreen-doctor not found!" >&2 - exit 1 -fi - -# Extract outputs list -enabled_outputs=$(jq -c '.outputs[] | select(.enabled == true)' "$PROFILE") -disabled_outputs=$(jq -c '.outputs[] | select(.enabled == false)' "$PROFILE") -outputs=$(jq -c '.outputs[]' "$PROFILE") - -# Restore enabled/disabled starting with the enabled monitors -# Starting with a disabled monitor might not work if it was -# previously the only enabled monitor - -function enable_outputs { - local outputs=$1 - - # If empty or only whitespace, return early - [[ -z "$outputs" ]] && return - - while IFS= read -r out; do - id=$(echo "$out" | jq -r '.id') - log "[VAR] id:" $id - name=$(echo "$out" | jq -r '.name') - log "[VAR] name:" $name - enabled=$(echo "$out" | jq -r '.enabled') - log "[VAR] enabled:" $enabled - - # Enable/disable - if [[ "$enabled" == "true" ]]; then - CMD="kscreen-doctor output.$name.enable" - log "[CMD]" $CMD - $CMD - else - CMD="kscreen-doctor output.$name.disable" - log "[CMD]" $CMD - $CMD - fi - done <<< "$outputs" -} - -log "Enabling enabled outputs..." -enable_outputs "$enabled_outputs" -log "Disabling disabled outputs..." -enable_outputs "$disabled_outputs" - -function apply_attribute { - output_id=$1 - attribute=$2 - value=$3 - value_map=$4 - - if [ $value != "null" ]; then - - if [[ -n "$value_map" ]]; then - log "[PREVALUE] Value supplied for $output_id $attribute: $value" - value=${value_map["$value"]} - log "[POSTVALUE] Value output for $output_id $attribute: $value" - fi - - CMD="kscreen-doctor output.$output_id.$attribute.$value" - log "[CMD]" $CMD - $CMD - else - log "Output $output_id has not attribute $attribute, skipping..." - fi -} - -function load_profile_to_outputs { - local outputs=$1 - - # If empty or only whitespace, return early - [[ -z "$outputs" ]] && return - - while IFS= read -r out; do - id=$(echo "$out" | jq -r '.id') - name=$(echo "$out" | jq -r '.name') - posx=$(echo "$out" | jq -r '.pos.x') - posy=$(echo "$out" | jq -r '.pos.y') - rotation=$(echo "$out" | jq -r '.rotation') - scale=$(echo "$out" | jq -r '.scale') - mode_id=$(echo "$out" | jq -r '.currentModeId') - brightness=$(echo "$out" | jq -r '.brightness') - brightness=$(awk "BEGIN {printf \"%d\", $brightness * 100}") - ddcCi=$(echo "$out" | jq -r '.ddcCi') - iccProfilePath=$(echo "$out" | jq -r '.iccProfilePath') - # mode_name=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .name") - # log "[VAR] mode_name:" $mode_name - refresh_rate=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .refreshRate") - refresh_rate=$(printf "%.0f" "$refresh_rate") - height=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .size.height") - width=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .size.width") - mode="${width}x${height}@${refresh_rate}" - replication_source_id=$(echo "$out" | jq -r ".replicationSource") - hdr=$(echo "$out" | jq -r ".hdr") - maxBpc=$(echo "$out" | jq -r ".maxBpc") - overscan=$(echo "$out" | jq -r ".overscan") - rgbRange=$(echo "$out" | jq -r ".rgbRange") - sdrbrightness=$(echo "$out" | jq -r '."sdr-brightness"') - vrrPolicy=$(echo "$out" | jq -r ".vrrPolicy") - wcg=$(echo "$out" | jq -r ".wcg") - - - declare -A bool_enable_map - bool_enable_map["true"]="enable" - bool_enable_map["false"]="disable" - - declare -A bool_allow_map - bool_allow_map["true"]="allow" - bool_allow_map["false"]="disallow" - - declare -A rgb_range_map - rgb_range_map["0"]="automatic" - rgb_range_map["full"]="full" - rgb_range_map["limited"]="limited" - - declare -A rotation_map - rotation_map["1"]="normal" - rotation_map["2"]="left" - rotation_map["4"]="inverted" - rotation_map["8"]="right" - - apply_attribute $name "wcg" $wcg $bool_enable_map - apply_attribute $name "sdr-brightness" $sdrbrightness - apply_attribute $name "vrrpolicy" $vrrPolicy - apply_attribute $name "rgbrange" $rgbRange $rgb_range_map - apply_attribute $name "overscan" $overscan - apply_attribute $name "hdr" $hdr $bool_enable_map - apply_attribute $name "brightness" $brightness - - if [ "$maxBpc" == 0 ]; then - maxBpc="automatic" - fi - apply_attribute $name "maxbpc" $maxBpc - apply_attribute $name "ddcCi" $ddcCi $bool_allow_map - - - log "[VAR] replication_source_id: $replication_source_id" - if [ $replication_source_id != 0 ]; then - replication_source_name=$(echo "$outputs.[] | select(.id == \"$replication_source_id\" | .name)" ) - apply_attribute $name "mirror" $replication_source_name - else - apply_attribute $name "mirror" "none" - fi - - priority=$(echo "$out" | jq -r '.priority') - - if [ "$iccProfilePath" != "" ]; then - apply_attribute $name "iccProfilePath" $iccProfilePath - fi - - - apply_attribute $name "mode" $mode - - # Position - # CMD="kscreen-doctor output.$name.position.$posx,$posy" - # log "[CMD]" $CMD - # $CMD - fullPosition="$posx,$posy" - apply_attribute $name "position" $fullPosition - - apply_attribute $name "scale" $scale - - # Rotation (map from JSON names to kscreen-doctor options) - # CMD="" - # case "$rotation" in - # "1") CMD="kscreen-doctor output.$name.rotation.normal" ;; - # "2") CMD="kscreen-doctor output.$name.rotation.left" ;; - # "4") CMD="kscreen-doctor output.$name.rotation.inverted" ;; - # "8") CMD="kscreen-doctor output.$name.rotation.right" ;; - # esac - # log "[CMD]" $CMD - # $CMD - apply_attribute $name "rotation" $rotation $rotation_map - - # Primary / Not Primary - if [ $priority -eq 1 ]; then - CMD="kscreen-doctor output.$name.primary" - log "[CMD]" $CMD - $CMD - fi - - CMD="kscreen-doctor output.$name.priority.$priority" - log "[CMD]" $CMD - $CMD - - done <<< "$outputs" -} - -load_profile_to_outputs "$outputs" - -echo "Display configuration restored." \ No newline at end of file diff --git a/save-display-profile.sh b/save-display-profile.sh deleted file mode 100755 index cb1f4d6..0000000 --- a/save-display-profile.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Check for correct usage -if [ $# -lt 1 ]; then - echo "Usage: $0 " - exit -fi - -OUTPUT_CONFIG_NAME=$1 -kscreen-doctor --json > $OUTPUT_CONFIG_NAME \ No newline at end of file