From 1d4e419548ae5931d89ba0a05c21e99e60a1a3c4 Mon Sep 17 00:00:00 2001 From: Dawson Matthews Date: Sun, 8 Mar 2026 23:26:59 -0600 Subject: [PATCH] modified layout --- kde-display-profile-manager.py | 127 +++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 46 deletions(-) diff --git a/kde-display-profile-manager.py b/kde-display-profile-manager.py index f45ad9f..4b39422 100755 --- a/kde-display-profile-manager.py +++ b/kde-display-profile-manager.py @@ -12,10 +12,11 @@ from pathlib import Path try: from PySide6.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, - QListWidget, QPushButton, QInputDialog, QMessageBox, QLabel, + QListWidget, QListWidgetItem, QPushButton, QInputDialog, QMessageBox, QLabel, QFileDialog ) - from PySide6.QtCore import Qt + from PySide6.QtGui import QIcon + from PySide6.QtCore import Qt, QSize PYSIDE_AVAILABLE = True except ImportError: PYSIDE_AVAILABLE = False @@ -220,32 +221,35 @@ class DisplayProfileManagerGUI(QMainWindow): self.setCentralWidget(central_widget) layout = QVBoxLayout(central_widget) - layout.addWidget(QLabel("Available Profiles:")) + # Header layout + header_layout = QHBoxLayout() + header_layout.addWidget(QLabel("Available Profiles:")) + header_layout.addStretch() + + self.refresh_btn = QPushButton() + self.refresh_btn.setIcon(QIcon.fromTheme("view-refresh")) + self.refresh_btn.setIconSize(QSize(20, 20)) + self.refresh_btn.setToolTip("Refresh Profiles") + self.refresh_btn.setFlat(True) + self.refresh_btn.clicked.connect(self.refresh_profiles) + header_layout.addWidget(self.refresh_btn) + + layout.addLayout(header_layout) self.profile_list = QListWidget() + self.profile_list.itemDoubleClicked.connect(self.on_load_clicked) layout.addWidget(self.profile_list) btn_layout = QHBoxLayout() - self.load_btn = QPushButton("Load Profile") - self.load_btn.clicked.connect(self.on_load_clicked) - btn_layout.addWidget(self.load_btn) - self.save_btn = QPushButton("Save Current") self.save_btn.clicked.connect(self.on_save_clicked) btn_layout.addWidget(self.save_btn) - - self.refresh_btn = QPushButton("Refresh") - self.refresh_btn.clicked.connect(self.refresh_profiles) - btn_layout.addWidget(self.refresh_btn) - self.delete_btn = QPushButton("Delete Profile") - self.delete_btn.clicked.connect(self.on_delete_clicked) - btn_layout.addWidget(self.delete_btn) + self.load_btn = QPushButton("Load Selected") + self.load_btn.clicked.connect(self.on_load_clicked) + btn_layout.addWidget(self.load_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) @@ -254,7 +258,44 @@ class DisplayProfileManagerGUI(QMainWindow): if DEFAULT_PROFILE_DIR.exists(): profiles = sorted(DEFAULT_PROFILE_DIR.glob("*.json")) for profile in profiles: - self.profile_list.addItem(profile.stem) + name = profile.stem + # Create item without text to prevent double-rendering/blurriness + item = QListWidgetItem(self.profile_list) + item.setData(Qt.UserRole, name) + + # Custom widget for the row + widget = QWidget() + row_layout = QHBoxLayout(widget) + row_layout.setContentsMargins(5, 2, 5, 2) + row_layout.setSpacing(5) + + label = QLabel(name) + # Ensure the label doesn't inherit transparency issues + label.setStyleSheet("background: transparent;") + row_layout.addWidget(label) + row_layout.addStretch() + + # Copy button + copy_btn = QPushButton() + copy_btn.setIcon(QIcon.fromTheme("edit-copy")) + copy_btn.setIconSize(QSize(16, 16)) + copy_btn.setFlat(True) + copy_btn.setToolTip("Copy Load Command") + copy_btn.clicked.connect(lambda checked=False, n=name: self.copy_profile_cmd(n)) + row_layout.addWidget(copy_btn) + + # Delete button + del_btn = QPushButton() + del_btn.setIcon(QIcon.fromTheme("user-trash")) + del_btn.setIconSize(QSize(16, 16)) + del_btn.setFlat(True) + del_btn.setToolTip("Delete Profile") + del_btn.clicked.connect(lambda checked=False, n=name: self.delete_profile(n)) + row_layout.addWidget(del_btn) + + item.setSizeHint(widget.sizeHint()) + self.profile_list.addItem(item) + self.profile_list.setItemWidget(item, widget) def get_default_profile_name(self): existing_names = [] @@ -286,13 +327,16 @@ class DisplayProfileManagerGUI(QMainWindow): except Exception as e: QMessageBox.critical(self, "Error", f"Failed to save profile: {e}") - def on_load_clicked(self): - selected_item = self.profile_list.currentItem() - if not selected_item: + def on_load_clicked(self, item=None): + if not isinstance(item, QListWidgetItem): + item = self.profile_list.currentItem() + + if not item: QMessageBox.warning(self, "No Selection", "Please select a profile to load.") return - profile_name = selected_item.text() + # Retrieve name from UserRole data instead of item.text() + profile_name = item.data(Qt.UserRole) profile_path = DEFAULT_PROFILE_DIR / f"{profile_name}.json" try: @@ -301,13 +345,17 @@ class DisplayProfileManagerGUI(QMainWindow): except Exception as e: QMessageBox.critical(self, "Error", f"Failed to load profile: {e}") - def on_delete_clicked(self): - selected_item = self.profile_list.currentItem() - if not selected_item: - QMessageBox.warning(self, "No Selection", "Please select a profile to delete.") - return + def copy_profile_cmd(self, profile_name): + 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))}" - profile_name = selected_item.text() + 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 delete_profile(self, profile_name): profile_path = DEFAULT_PROFILE_DIR / f"{profile_name}.json" reply = QMessageBox.question(self, "Confirm Delete", @@ -322,28 +370,15 @@ class DisplayProfileManagerGUI(QMainWindow): except Exception as e: QMessageBox.critical(self, "Error", f"Failed to delete 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) sys.exit(1) + # Use 'Round' instead of 'PassThrough' as it is often more stable for font rendering + if hasattr(Qt, "HighDpiScaleFactorRoundingPolicy"): + QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.Round) + app = QApplication(sys.argv) window = DisplayProfileManagerGUI() window.show()