neiam
/home-assistant-plasmoid
Home Assistant Plasmoid
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
controls in popup thingy
ac76a3b · gmorell · 2025-06-23 22:13
Files changed
modified
contents/ui/EntityControl.qml
+192
−136
@@ -49,12 +49,10 @@ Item {
| 49 | 49 | } |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | − readonly property bool hasExpandedControls: isLight && controlType === "light" && showExpandedControls && (supportsRgb || supportsCct || supportsBrightness) | |
| 52 | + readonly property bool hasAdvancedControls: isLight && controlType === "light" && (supportsRgb || supportsCct || supportsBrightness) | |
| 53 | 53 | |
| 54 | − width: hasExpandedControls ? Math.max(buttonSizePixels * 4, Kirigami.Units.gridUnit * 8) : | |
| 55 | − buttonSizePixels + (showLabel ? Kirigami.Units.smallSpacing : 0) | |
| 56 | − height: hasExpandedControls ? buttonSizePixels + Kirigami.Units.gridUnit * 10 + (showLabel ? Kirigami.Units.gridUnit : 0) : | |
| 57 | − buttonSizePixels + (showLabel ? Kirigami.Units.gridUnit : 0) | |
| 54 | + width: buttonSizePixels + (showLabel ? Kirigami.Units.smallSpacing : 0) | |
| 55 | + height: buttonSizePixels + (showLabel ? Kirigami.Units.gridUnit : 0) | |
| 58 | 56 | |
| 59 | 57 | ColumnLayout { |
| 60 | 58 | anchors.fill: parent |
@@ -85,16 +83,14 @@ Item {
| 85 | 83 | |
| 86 | 84 | // Advanced controls indicator for lights |
| 87 | 85 | Rectangle { |
| 88 | − visible: isLight && controlType === "light" && (supportsRgb || supportsCct || supportsBrightness) | |
| 86 | + visible: hasAdvancedControls | |
| 89 | 87 | anchors.top: parent.top |
| 90 | 88 | anchors.right: parent.right |
| 91 | 89 | anchors.margins: 2 |
| 92 | 90 | width: 6 |
| 93 | 91 | height: 6 |
| 94 | 92 | radius: 3 |
| 95 | − color: showExpandedControls ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor | |
| 96 | − | |
| 97 | − Behavior on color { ColorAnimation { duration: 150 } } | |
| 93 | + color: Kirigami.Theme.disabledTextColor | |
| 98 | 94 | } |
| 99 | 95 | } |
| 100 | 96 |
@@ -125,13 +121,13 @@ Item {
| 125 | 121 | |
| 126 | 122 | onClicked: handleControlClick() |
| 127 | 123 | |
| 128 | − // Right-click to toggle expanded controls for lights | |
| 124 | + // Right-click to show advanced controls popup for lights | |
| 129 | 125 | MouseArea { |
| 130 | 126 | anchors.fill: parent |
| 131 | 127 | acceptedButtons: Qt.RightButton |
| 132 | 128 | onClicked: { |
| 133 | − if (isLight && controlType === "light" && (supportsRgb || supportsCct || supportsBrightness)) { | |
| 134 | − showExpandedControls = !showExpandedControls | |
| 129 | + if (hasAdvancedControls) { | |
| 130 | + advancedControlsPopup.open() | |
| 135 | 131 | } |
| 136 | 132 | } |
| 137 | 133 | } |
@@ -150,158 +146,219 @@ Item {
| 150 | 146 | |
| 151 | 147 | Behavior on color { ColorAnimation { duration: 150 } } |
| 152 | 148 | } |
| 149 | + } | |
| 150 | + | |
| 151 | + // Advanced Controls Popup | |
| 152 | + QQC2.Popup { | |
| 153 | + id: advancedControlsPopup | |
| 154 | + parent: entityControl | |
| 155 | + modal: true | |
| 156 | + focus: true | |
| 157 | + closePolicy: QQC2.Popup.CloseOnEscape | QQC2.Popup.CloseOnPressOutside | |
| 153 | 158 | |
| 154 | − // Expanded Light Controls | |
| 155 | − Rectangle { | |
| 156 | − visible: hasExpandedControls | |
| 157 | − Layout.fillWidth: true | |
| 158 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 7 | |
| 159 | + width: Kirigami.Units.gridUnit * 16 | |
| 160 | + height: Kirigami.Units.gridUnit * 12 | |
| 161 | + | |
| 162 | + x: (parent.width - width) / 2 | |
| 163 | + y: parent.height + Kirigami.Units.smallSpacing | |
| 164 | + | |
| 165 | + background: Rectangle { | |
| 159 | 166 | color: Kirigami.Theme.backgroundColor |
| 160 | 167 | border.color: Kirigami.Theme.separatorColor |
| 161 | 168 | border.width: 1 |
| 162 | 169 | radius: Kirigami.Units.cornerRadius |
| 163 | 170 | |
| 164 | − ColumnLayout { | |
| 171 | + // Add a subtle shadow effect | |
| 172 | + Rectangle { | |
| 165 | 173 | anchors.fill: parent |
| 166 | − anchors.margins: Kirigami.Units.smallSpacing | |
| 167 | − spacing: Kirigami.Units.smallSpacing | |
| 174 | + anchors.margins: -2 | |
| 175 | + z: -1 | |
| 176 | + color: "transparent" | |
| 177 | + border.color: Qt.rgba(0, 0, 0, 0.1) | |
| 178 | + border.width: 1 | |
| 179 | + radius: Kirigami.Units.cornerRadius + 1 | |
| 180 | + } | |
| 181 | + } | |
| 182 | + contentItem: ColumnLayout { | |
| 183 | + spacing: Kirigami.Units.largeSpacing | |
| 184 | + | |
| 185 | + // Popup Header | |
| 186 | + RowLayout { | |
| 187 | + Layout.fillWidth: true | |
| 188 | + | |
| 189 | + Kirigami.Icon { | |
| 190 | + source: getIconName() | |
| 191 | + Layout.preferredWidth: Kirigami.Units.iconSizes.small | |
| 192 | + Layout.preferredHeight: Kirigami.Units.iconSizes.small | |
| 193 | + color: isOn ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.textColor | |
| 194 | + } | |
| 195 | + | |
| 196 | + PlasmaComponents3.Label { | |
| 197 | + text: displayName | |
| 198 | + font.bold: true | |
| 199 | + Layout.fillWidth: true | |
| 200 | + } | |
| 201 | + | |
| 202 | + PlasmaComponents3.Button { | |
| 203 | + icon.name: "window-close" | |
| 204 | + flat: true | |
| 205 | + onClicked: advancedControlsPopup.close() | |
| 206 | + } | |
| 207 | + } | |
| 208 | + | |
| 209 | + // Brightness Control | |
| 210 | + RowLayout { | |
| 211 | + visible: supportsBrightness && isOn | |
| 212 | + Layout.fillWidth: true | |
| 213 | + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5 | |
| 214 | + | |
| 215 | + Kirigami.Icon { | |
| 216 | + source: "brightness-low" | |
| 217 | + Layout.preferredWidth: Kirigami.Units.iconSizes.small | |
| 218 | + Layout.preferredHeight: Kirigami.Units.iconSizes.small | |
| 219 | + } | |
| 168 | 220 | |
| 169 | − // Brightness Control | |
| 170 | − RowLayout { | |
| 171 | − visible: supportsBrightness && isOn | |
| 221 | + PlasmaComponents3.Label { | |
| 222 | + text: "Brightness" | |
| 223 | + Layout.preferredWidth: Kirigami.Units.gridUnit * 3 | |
| 224 | + } | |
| 225 | + | |
| 226 | + QQC2.Slider { | |
| 227 | + id: popupBrightnessSlider | |
| 172 | 228 | Layout.fillWidth: true |
| 173 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2 | |
| 229 | + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5 | |
| 230 | + from: 1 | |
| 231 | + to: 100 | |
| 232 | + value: currentBrightness | |
| 233 | + stepSize: 1 | |
| 174 | 234 | |
| 175 | − Kirigami.Icon { | |
| 176 | − source: "brightness-low" | |
| 177 | − Layout.preferredWidth: Kirigami.Units.iconSizes.small | |
| 178 | − Layout.preferredHeight: Kirigami.Units.iconSizes.small | |
| 235 | + onMoved: { | |
| 236 | + var brightnessValue = Math.round(value * 255 / 100) | |
| 237 | + controlActivated(entityId, "turn_on", { brightness: brightnessValue }) | |
| 179 | 238 | } |
| 180 | 239 | |
| 181 | − QQC2.Slider { | |
| 182 | − id: brightnessSlider | |
| 183 | − Layout.fillWidth: true | |
| 184 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2 | |
| 185 | − from: 1 | |
| 186 | − to: 100 | |
| 187 | − value: currentBrightness | |
| 188 | − stepSize: 1 | |
| 189 | − | |
| 190 | − onMoved: { | |
| 191 | − // Send brightness command on slider move | |
| 192 | − var brightnessValue = Math.round(value * 255 / 100) | |
| 193 | − controlActivated(entityId, "turn_on", { brightness: brightnessValue }) | |
| 194 | − } | |
| 240 | + background: Rectangle { | |
| 241 | + x: popupBrightnessSlider.leftPadding | |
| 242 | + y: popupBrightnessSlider.topPadding + popupBrightnessSlider.availableHeight / 2 - height / 2 | |
| 243 | + implicitWidth: 200 | |
| 244 | + implicitHeight: 8 | |
| 245 | + width: popupBrightnessSlider.availableWidth | |
| 246 | + height: implicitHeight | |
| 247 | + radius: 4 | |
| 248 | + color: Kirigami.Theme.backgroundColor | |
| 249 | + border.color: Kirigami.Theme.separatorColor | |
| 195 | 250 | |
| 196 | − background: Rectangle { | |
| 197 | − x: brightnessSlider.leftPadding | |
| 198 | − y: brightnessSlider.topPadding + brightnessSlider.availableHeight / 2 - height / 2 | |
| 199 | − implicitWidth: 200 | |
| 200 | − implicitHeight: 8 | |
| 201 | − width: brightnessSlider.availableWidth | |
| 202 | − height: implicitHeight | |
| 251 | + Rectangle { | |
| 252 | + width: popupBrightnessSlider.visualPosition * parent.width | |
| 253 | + height: parent.height | |
| 254 | + color: Kirigami.Theme.highlightColor | |
| 203 | 255 | radius: 4 |
| 204 | − color: Kirigami.Theme.backgroundColor | |
| 205 | − border.color: Kirigami.Theme.separatorColor | |
| 206 | − | |
| 207 | − Rectangle { | |
| 208 | − width: brightnessSlider.visualPosition * parent.width | |
| 209 | − height: parent.height | |
| 210 | − color: Kirigami.Theme.highlightColor | |
| 211 | − radius: 4 | |
| 212 | − } | |
| 213 | − } | |
| 214 | − | |
| 215 | − handle: Rectangle { | |
| 216 | − x: brightnessSlider.leftPadding + brightnessSlider.visualPosition * (brightnessSlider.availableWidth - width) | |
| 217 | − y: brightnessSlider.topPadding + brightnessSlider.availableHeight / 2 - height / 2 | |
| 218 | − implicitWidth: 20 | |
| 219 | − implicitHeight: 20 | |
| 220 | − radius: 10 | |
| 221 | − color: brightnessSlider.pressed ? Qt.darker(Kirigami.Theme.highlightColor, 1.1) : Kirigami.Theme.highlightColor | |
| 222 | − border.color: Kirigami.Theme.backgroundColor | |
| 223 | − border.width: 2 | |
| 224 | 256 | } |
| 225 | 257 | } |
| 226 | 258 | |
| 227 | − PlasmaComponents3.Label { | |
| 228 | − text: currentBrightness + "%" | |
| 229 | − font.pointSize: Kirigami.Theme.smallFont.pointSize | |
| 230 | − Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5 | |
| 259 | + handle: Rectangle { | |
| 260 | + x: popupBrightnessSlider.leftPadding + popupBrightnessSlider.visualPosition * (popupBrightnessSlider.availableWidth - width) | |
| 261 | + y: popupBrightnessSlider.topPadding + popupBrightnessSlider.availableHeight / 2 - height / 2 | |
| 262 | + implicitWidth: 20 | |
| 263 | + implicitHeight: 20 | |
| 264 | + radius: 10 | |
| 265 | + color: popupBrightnessSlider.pressed ? Qt.darker(Kirigami.Theme.highlightColor, 1.1) : Kirigami.Theme.highlightColor | |
| 266 | + border.color: Kirigami.Theme.backgroundColor | |
| 267 | + border.width: 2 | |
| 231 | 268 | } |
| 232 | 269 | } |
| 233 | 270 | |
| 234 | − // Color Temperature Control | |
| 235 | − RowLayout { | |
| 236 | − visible: supportsCct && isOn // Show alongside RGB controls | |
| 271 | + PlasmaComponents3.Label { | |
| 272 | + text: currentBrightness + "%" | |
| 273 | + Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5 | |
| 274 | + } | |
| 275 | + } | |
| 276 | + | |
| 277 | + // Color Temperature Control | |
| 278 | + RowLayout { | |
| 279 | + visible: supportsCct && isOn | |
| 280 | + Layout.fillWidth: true | |
| 281 | + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5 | |
| 282 | + | |
| 283 | + Kirigami.Icon { | |
| 284 | + source: "weather-clear-night" | |
| 285 | + Layout.preferredWidth: Kirigami.Units.iconSizes.small | |
| 286 | + Layout.preferredHeight: Kirigami.Units.iconSizes.small | |
| 287 | + } | |
| 288 | + | |
| 289 | + PlasmaComponents3.Label { | |
| 290 | + text: "Color Temp" | |
| 291 | + Layout.preferredWidth: Kirigami.Units.gridUnit * 3 | |
| 292 | + } | |
| 293 | + | |
| 294 | + QQC2.Slider { | |
| 295 | + id: popupColorTempSlider | |
| 237 | 296 | Layout.fillWidth: true |
| 238 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2 | |
| 297 | + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5 | |
| 298 | + from: 153 // ~6500K (cool) | |
| 299 | + to: 500 // ~2000K (warm) | |
| 300 | + value: currentColorTemp | |
| 301 | + stepSize: 1 | |
| 239 | 302 | |
| 240 | − Kirigami.Icon { | |
| 241 | − source: "weather-clear-night" | |
| 242 | − Layout.preferredWidth: Kirigami.Units.iconSizes.small | |
| 243 | − Layout.preferredHeight: Kirigami.Units.iconSizes.small | |
| 303 | + onMoved: { | |
| 304 | + controlActivated(entityId, "turn_on", { color_temp: Math.round(value) }) | |
| 244 | 305 | } |
| 245 | 306 | |
| 246 | − QQC2.Slider { | |
| 247 | − id: colorTempSlider | |
| 248 | − Layout.fillWidth: true | |
| 249 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2 | |
| 250 | − from: 153 // ~6500K (cool) | |
| 251 | − to: 500 // ~2000K (warm) | |
| 252 | − value: currentColorTemp | |
| 253 | − stepSize: 1 | |
| 307 | + background: Rectangle { | |
| 308 | + x: popupColorTempSlider.leftPadding | |
| 309 | + y: popupColorTempSlider.topPadding + popupColorTempSlider.availableHeight / 2 - height / 2 | |
| 310 | + implicitWidth: 200 | |
| 311 | + implicitHeight: 8 | |
| 312 | + width: popupColorTempSlider.availableWidth | |
| 313 | + height: implicitHeight | |
| 314 | + radius: 4 | |
| 254 | 315 | |
| 255 | − onMoved: { | |
| 256 | − controlActivated(entityId, "turn_on", { color_temp: Math.round(value) }) | |
| 316 | + gradient: Gradient { | |
| 317 | + orientation: Gradient.Horizontal | |
| 318 | + GradientStop { position: 0.0; color: "#87CEEB" } // Cool blue | |
| 319 | + GradientStop { position: 1.0; color: "#FFA500" } // Warm orange | |
| 257 | 320 | } |
| 258 | 321 | |
| 259 | − background: Rectangle { | |
| 260 | − x: colorTempSlider.leftPadding | |
| 261 | − y: colorTempSlider.topPadding + colorTempSlider.availableHeight / 2 - height / 2 | |
| 262 | − implicitWidth: 200 | |
| 263 | − implicitHeight: 8 | |
| 264 | − width: colorTempSlider.availableWidth | |
| 265 | − height: implicitHeight | |
| 266 | − radius: 4 | |
| 267 | − | |
| 268 | − gradient: Gradient { | |
| 269 | − orientation: Gradient.Horizontal | |
| 270 | − GradientStop { position: 0.0; color: "#87CEEB" } // Cool blue | |
| 271 | − GradientStop { position: 1.0; color: "#FFA500" } // Warm orange | |
| 272 | − } | |
| 273 | − | |
| 274 | − border.color: Kirigami.Theme.separatorColor | |
| 275 | − border.width: 1 | |
| 276 | − } | |
| 277 | − | |
| 278 | − handle: Rectangle { | |
| 279 | − x: colorTempSlider.leftPadding + colorTempSlider.visualPosition * (colorTempSlider.availableWidth - width) | |
| 280 | − y: colorTempSlider.topPadding + colorTempSlider.availableHeight / 2 - height / 2 | |
| 281 | − implicitWidth: 20 | |
| 282 | − implicitHeight: 20 | |
| 283 | − radius: 10 | |
| 284 | − color: colorTempSlider.pressed ? Qt.darker(Kirigami.Theme.highlightColor, 1.1) : Kirigami.Theme.highlightColor | |
| 285 | − border.color: Kirigami.Theme.backgroundColor | |
| 286 | − border.width: 2 | |
| 287 | − } | |
| 322 | + border.color: Kirigami.Theme.separatorColor | |
| 323 | + border.width: 1 | |
| 288 | 324 | } |
| 289 | 325 | |
| 290 | − PlasmaComponents3.Label { | |
| 291 | − text: Math.round(1000000 / currentColorTemp) + "K" | |
| 292 | − font.pointSize: Kirigami.Theme.smallFont.pointSize | |
| 293 | − Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5 | |
| 326 | + handle: Rectangle { | |
| 327 | + x: popupColorTempSlider.leftPadding + popupColorTempSlider.visualPosition * (popupColorTempSlider.availableWidth - width) | |
| 328 | + y: popupColorTempSlider.topPadding + popupColorTempSlider.availableHeight / 2 - height / 2 | |
| 329 | + implicitWidth: 20 | |
| 330 | + implicitHeight: 20 | |
| 331 | + radius: 10 | |
| 332 | + color: popupColorTempSlider.pressed ? Qt.darker(Kirigami.Theme.highlightColor, 1.1) : Kirigami.Theme.highlightColor | |
| 333 | + border.color: Kirigami.Theme.backgroundColor | |
| 334 | + border.width: 2 | |
| 294 | 335 | } |
| 295 | 336 | } |
| 296 | 337 | |
| 297 | − // RGB Color Control | |
| 298 | − RowLayout { | |
| 299 | − visible: supportsRgb && isOn | |
| 338 | + PlasmaComponents3.Label { | |
| 339 | + text: Math.round(1000000 / currentColorTemp) + "K" | |
| 340 | + Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5 | |
| 341 | + } | |
| 342 | + } | |
| 343 | + | |
| 344 | + // RGB Color Control | |
| 345 | + ColumnLayout { | |
| 346 | + visible: supportsRgb && isOn | |
| 347 | + Layout.fillWidth: true | |
| 348 | + spacing: Kirigami.Units.smallSpacing | |
| 349 | + | |
| 350 | + PlasmaComponents3.Label { | |
| 351 | + text: "RGB Colors" | |
| 352 | + font.bold: true | |
| 353 | + } | |
| 354 | + | |
| 355 | + // Color preset buttons | |
| 356 | + GridLayout { | |
| 300 | 357 | Layout.fillWidth: true |
| 301 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5 | |
| 302 | − spacing: Kirigami.Units.smallSpacing | |
| 358 | + columns: 7 | |
| 359 | + columnSpacing: Kirigami.Units.smallSpacing | |
| 360 | + rowSpacing: Kirigami.Units.smallSpacing | |
| 303 | 361 | |
| 304 | − // Color preset buttons | |
| 305 | 362 | Repeater { |
| 306 | 363 | model: [ |
| 307 | 364 | { color: "#FF0000", name: "Red" }, |
@@ -314,15 +371,15 @@ Item {
| 314 | 371 | ] |
| 315 | 372 | |
| 316 | 373 | PlasmaComponents3.Button { |
| 317 | − Layout.preferredWidth: Kirigami.Units.gridUnit * 1.2 | |
| 318 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2 | |
| 374 | + Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5 | |
| 375 | + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5 | |
| 319 | 376 | |
| 320 | 377 | background: Rectangle { |
| 321 | 378 | radius: Kirigami.Units.cornerRadius |
| 322 | 379 | color: modelData.color |
| 323 | 380 | border.color: Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 1.0) === color ? |
| 324 | 381 | Kirigami.Theme.highlightColor : Kirigami.Theme.separatorColor |
| 325 | − border.width: Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 1.0) === color ? 2 : 1 | |
| 382 | + border.width: Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 1.0) === color ? 3 : 1 | |
| 326 | 383 | } |
| 327 | 384 | |
| 328 | 385 | PlasmaComponents3.ToolTip { |
@@ -339,9 +396,8 @@ Item {
| 339 | 396 | |
| 340 | 397 | // Current color indicator |
| 341 | 398 | Rectangle { |
| 342 | − visible: supportsRgb && isOn | |
| 343 | 399 | Layout.fillWidth: true |
| 344 | − Layout.preferredHeight: Kirigami.Units.gridUnit * 0.8 | |
| 400 | + Layout.preferredHeight: Kirigami.Units.gridUnit * 1 | |
| 345 | 401 | radius: Kirigami.Units.cornerRadius |
| 346 | 402 | color: Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 1.0) |
| 347 | 403 | border.color: Kirigami.Theme.separatorColor |
@@ -349,7 +405,7 @@ Item {
| 349 | 405 | |
| 350 | 406 | PlasmaComponents3.Label { |
| 351 | 407 | anchors.centerIn: parent |
| 352 | − text: "RGB: " + currentRgbColor[0] + ", " + currentRgbColor[1] + ", " + currentRgbColor[2] | |
| 408 | + text: "Current: RGB(" + currentRgbColor[0] + ", " + currentRgbColor[1] + ", " + currentRgbColor[2] + ")" | |
| 353 | 409 | font.pointSize: Kirigami.Theme.smallFont.pointSize |
| 354 | 410 | color: (currentRgbColor[0] + currentRgbColor[1] + currentRgbColor[2]) > 384 ? "black" : "white" |
| 355 | 411 | } |
Parents: acca0da