Fix Plasma Shell freeze when selecting an entity (v2.0.1)

50de478 · Gabriel Morell · 2026-09-26 04:51

7 files +69 -24
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