neiam
/home-assistant-plasmoid
Home Assistant Plasmoid
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
Fix Plasma Shell freeze when selecting an entity (v2.0.1)
50de478 · Gabriel Morell · 2026-09-26 04:51
Message
{commit_body(@commit)}
Files changed
modified
.gitignore
+3
−0
@@ -52,3 +52,6 @@ wheels/
| 52 | 52 | # Local configuration files |
| 53 | 53 | config.local.json |
| 54 | 54 | settings.local.json |
| 55 | + | |
| 56 | +# Secrets (Home Assistant token for local testing) | |
| 57 | +.env |
modified
contents/ui/EntityBrowser.qml
+58
−11
@@ -12,6 +12,8 @@ QQC2.ComboBox {
| 12 | 12 | property var selectedEntity: null |
| 13 | 13 | property var filteredDomains: [] // Empty = all domains, or ["light", "switch"] etc. |
| 14 | 14 | property string searchQuery: "" |
| 15 | + // Set while editText is changed programmatically so it doesn't trigger a re-filter | |
| 16 | + property bool suppressFilter: false | |
| 15 | 17 | |
| 16 | 18 | signal entitySelected(var entity) |
| 17 | 19 |
@@ -25,20 +27,59 @@ QQC2.ComboBox {
| 25 | 27 | } |
| 26 | 28 | |
| 27 | 29 | onEditTextChanged: { |
| 30 | + if (suppressFilter) { | |
| 31 | + return | |
| 32 | + } | |
| 28 | 33 | searchQuery = editText |
| 29 | − filterEntities() | |
| 34 | + // Defer so the model is never rebuilt from inside a ComboBox/delegate signal handler | |
| 35 | + filterTimer.restart() | |
| 30 | 36 | } |
| 31 | 37 | |
| 32 | 38 | onActivated: function(index) { |
| 33 | 39 | if (index >= 0 && index < entityModel.count) { |
| 34 | − var entity = entityModel.get(index) | |
| 35 | − selectedEntityId = entity.entity_id | |
| 36 | − selectedEntityName = entity.friendly_name | |
| 37 | − selectedEntity = entity | |
| 38 | − entitySelected(entity) | |
| 40 | + selectEntity(entityModel.get(index)) | |
| 39 | 41 | } |
| 40 | 42 | } |
| 41 | 43 | |
| 44 | + Timer { | |
| 45 | + id: filterTimer | |
| 46 | + interval: 150 | |
| 47 | + onTriggered: filterEntities() | |
| 48 | + } | |
| 49 | + | |
| 50 | + function setEditTextSilently(text) { | |
| 51 | + suppressFilter = true | |
| 52 | + editText = text | |
| 53 | + suppressFilter = false | |
| 54 | + } | |
| 55 | + | |
| 56 | + function clearSelection() { | |
| 57 | + setEditTextSilently("") | |
| 58 | + searchQuery = "" | |
| 59 | + selectedEntityId = "" | |
| 60 | + selectedEntityName = "" | |
| 61 | + selectedEntity = null | |
| 62 | + } | |
| 63 | + | |
| 64 | + function selectEntity(item) { | |
| 65 | + // Copy into a plain object: model/ListModel proxies become invalid once the model is rebuilt | |
| 66 | + var entity = { | |
| 67 | + entity_id: item.entity_id, | |
| 68 | + friendly_name: item.friendly_name, | |
| 69 | + domain: item.domain, | |
| 70 | + state: item.state, | |
| 71 | + icon: item.icon, | |
| 72 | + device_class: item.device_class, | |
| 73 | + unit_of_measurement: item.unit_of_measurement, | |
| 74 | + display_text: item.display_text | |
| 75 | + } | |
| 76 | + selectedEntityId = entity.entity_id | |
| 77 | + selectedEntityName = entity.friendly_name | |
| 78 | + selectedEntity = entity | |
| 79 | + setEditTextSilently(entity.display_text) | |
| 80 | + entitySelected(entity) | |
| 81 | + } | |
| 82 | + | |
| 42 | 83 | // Custom popup for better entity browsing |
| 43 | 84 | popup: QQC2.Popup { |
| 44 | 85 | id: entityPopup |
@@ -162,12 +203,8 @@ QQC2.ComboBox {
| 162 | 203 | } |
| 163 | 204 | |
| 164 | 205 | onClicked: { |
| 165 | − entityBrowser.currentIndex = index | |
| 166 | − selectedEntityId = model.entity_id | |
| 167 | − selectedEntityName = model.friendly_name | |
| 168 | − selectedEntity = model | |
| 169 | − entitySelected(model) | |
| 170 | 206 | entityPopup.close() |
| 207 | + selectEntity(model) | |
| 171 | 208 | } |
| 172 | 209 | } |
| 173 | 210 | } |
@@ -214,6 +251,16 @@ QQC2.ComboBox {
| 214 | 251 | } |
| 215 | 252 | |
| 216 | 253 | function filterEntities() { |
| 254 | + // Rebuilding the model makes the editable ComboBox reset editText, which would | |
| 255 | + // wipe the user's query and re-trigger filtering; keep the text and suppress that. | |
| 256 | + var typedText = editText | |
| 257 | + suppressFilter = true | |
| 258 | + rebuildModel() | |
| 259 | + editText = typedText | |
| 260 | + suppressFilter = false | |
| 261 | + } | |
| 262 | + | |
| 263 | + function rebuildModel() { | |
| 217 | 264 | entityModel.clear() |
| 218 | 265 | |
| 219 | 266 | if (!homeAssistantAPI.allEntities || homeAssistantAPI.allEntities.length === 0) { |
modified
contents/ui/configEntities.qml
+6
−12
@@ -87,10 +87,7 @@ KCM.SimpleKCM {
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | function clearAddForm() { |
| 90 | − entityBrowser.editText = "" | |
| 91 | − entityBrowser.selectedEntityId = "" | |
| 92 | − entityBrowser.selectedEntityName = "" | |
| 93 | − entityBrowser.selectedEntity = null | |
| 90 | + entityBrowser.clearSelection() | |
| 94 | 91 | newEntityIdField.text = "" |
| 95 | 92 | newEntityNameField.text = "" |
| 96 | 93 | newEntityIconField.text = "" |
@@ -278,14 +275,11 @@ KCM.SimpleKCM {
| 278 | 275 | Kirigami.FormData.label: i18n("Entity ID:") |
| 279 | 276 | placeholderText: i18n("e.g., light.living_room") |
| 280 | 277 | |
| 281 | − onTextChanged: { | |
| 282 | − if (text.trim()) { | |
| 283 | − // Clear entity browser selection when manually typing | |
| 284 | − entityBrowser.editText = "" | |
| 285 | − entityBrowser.selectedEntityId = text.trim() | |
| 286 | − entityBrowser.selectedEntityName = "" | |
| 287 | − entityBrowser.selectedEntity = null | |
| 288 | − } | |
| 278 | + // textEdited only fires for user input, not when onEntitySelected fills this field | |
| 279 | + onTextEdited: { | |
| 280 | + // Clear entity browser selection when manually typing | |
| 281 | + entityBrowser.clearSelection() | |
| 282 | + entityBrowser.selectedEntityId = text.trim() | |
| 289 | 283 | } |
| 290 | 284 | } |
| 291 | 285 |
modified
metadata.json
+1
−1
@@ -11,7 +11,7 @@
| 11 | 11 | "Icon": "home", |
| 12 | 12 | "Id": "org.neiam.kde.homeassistant", |
| 13 | 13 | "Name": "Home Assistant Control", |
| 14 | − "Version": "2.0", | |
| 14 | + "Version": "2.0.1", | |
| 15 | 15 | "Website": "http://neiam.org" |
| 16 | 16 | }, |
| 17 | 17 | "KPackageStructure": "Plasma/Applet", |
modified
package.sh
+1
−0
@@ -28,6 +28,7 @@ rsync -av \
| 28 | 28 | --exclude='package.sh' \ |
| 29 | 29 | --exclude='node_modules' \ |
| 30 | 30 | --exclude='*.log' \ |
| 31 | + --exclude='.env' \ | |
| 31 | 32 | . "$PACKAGE_DIR/" |
| 32 | 33 | |
| 33 | 34 | # Update version in metadata.json if not "dev" |
Parents: fe8dc15