From 69458631dc6336b33a17d94b3e3a0673995fd995 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sat, 1 Aug 2026 11:48:59 +0200 Subject: [PATCH] gui: fix session tree view delegate crashes and scrollable input - Guard delegate against undefined properties during initial render - Use || 0 fallbacks for optional model properties - Remove broken ScrollBar.vertical.value assignment (not assignable) - Fix Keys.onReturnPressed to use explicit function(event) parameter - Call buildSessionTree() on Component.onCompleted --- gui/main.qml | 81 ++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/gui/main.qml b/gui/main.qml index 428d363..966e9b2 100644 --- a/gui/main.qml +++ b/gui/main.qml @@ -73,11 +73,13 @@ ApplicationWindow { } function buildSessionTree() { + console.log("buildSessionTree: sessions count = " + ollie.sessions.length) sessionTreeModel.clear() var sessions = ollie.sessions for (var i = 0; i < sessions.length; ++i) { - var sess = sessions[i].toMap() + var sess = sessions[i] var sid = sess.id || "" + console.log(" session[" + i + "] = " + sid) // Auto-expand active session var expanded = (sid === ollie.activeSessionId) // Add session node @@ -91,19 +93,25 @@ ApplicationWindow { displayName: sid }) // Fetch agents and add them - var agents = ollie.getAgents(sid) - for (var j = 0; j < agents.length; ++j) { - var aid = agents[j] - sessionTreeModel.append({ - type: "agent", - parentId: sid, - agentId: aid, - level: 1, - state: "idle", - displayName: "Agent " + aid - }) + try { + var agents = ollie.getAgents(sid) + console.log(" agents for " + sid + ": " + agents.length) + for (var j = 0; j < agents.length; ++j) { + var aid = agents[j] + sessionTreeModel.append({ + type: "agent", + parentId: sid, + agentId: aid, + level: 1, + state: "idle", + displayName: "Agent " + aid + }) + } + } catch(e) { + console.log(" error getting agents for " + sid + ": " + e) } } + console.log(" total tree items: " + sessionTreeModel.count) } function toggleExpand(index) { @@ -131,6 +139,7 @@ ApplicationWindow { chatModel.trimFront(30) } scrollTimer.start() + buildSessionTree() } Connections { @@ -305,54 +314,47 @@ ApplicationWindow { delegate: ItemDelegate { width: sessionList.width + + // Guard against undefined during initial render height: { - if (modelData.type === "agent" && !parentSessionExpanded(modelData.parentId)) + if (!type) return 0 + if (type === "agent" && !parentSessionExpanded(parentId)) return 0 return 28 } visible: height > 0 - property var _parentItem: null - contentItem: RowLayout { anchors.fill: parent spacing: 0 - // Expand/collapse indicator + // Indent + expand/collapse indicator Label { - Layout.leftPadding: modelData.level * 16 + 4 - Layout.preferredWidth: 16 - text: modelData.type === "session" ? (modelData.expanded ? "▼" : "▶") : "" + Layout.preferredWidth: (level || 0) * 16 + 16 + text: type === "session" ? (expanded ? "▼" : "▶") : "" font.pixelSize: theme.fontSize > 0 ? theme.fontSize * 0.7 : 10 color: theme.textColor opacity: 0.6 - } - - // Icon/type indicator - Label { - Layout.preferredWidth: 16 - text: modelData.type === "session" ? "📁" : "🤖" - font.pixelSize: theme.fontSize > 0 ? theme.fontSize * 0.8 : 11 + verticalAlignment: Text.AlignVCenter } // Name Label { Layout.fillWidth: true - text: modelData.displayName || "" + text: displayName || "" color: theme.textColor font.pointSize: theme.fontSize > 0 ? theme.fontSize : Qt.application.font.pointSize verticalAlignment: Text.AlignVCenter - leftPadding: 4 } // State dot Rectangle { Layout.preferredWidth: 8 Layout.preferredHeight: 8 + Layout.alignment: Qt.AlignVCenter radius: 4 - anchors.verticalCenter: parent.verticalCenter color: { - var s = modelData.state || "idle" + var s = state || "idle" if (s === "idle") return "#4caf50" if (s.startsWith("calling")) return "#ff9800" return "#2196f3" @@ -361,19 +363,19 @@ ApplicationWindow { } onClicked: { - if (modelData.type === "session") { + if (type === "session") { toggleExpand(index) - } else if (modelData.type === "agent") { - activateAgent(modelData.parentId, modelData.agentId) + } else if (type === "agent") { + activateAgent(parentId, agentId) } } - highlighted: (modelData.type === "agent" && modelData.agentId === ollie.activeAgentId && modelData.parentId === ollie.activeSessionId) + highlighted: (type === "agent" && agentId === ollie.activeAgentId && parentId === ollie.activeSessionId) - function parentSessionExpanded(parentId) { + function parentSessionExpanded(pid) { for (var i = 0; i < sessionTreeModel.count; ++i) { var item = sessionTreeModel.get(i) - if (item.id === parentId && item.type === "session") + if (item.id === pid && item.type === "session") return item.expanded } return false @@ -554,6 +556,7 @@ ApplicationWindow { spacing: 4 ScrollView { + id: promptScroll Layout.fillWidth: true Layout.maximumHeight: 200 Layout.preferredHeight: Math.min(promptInput.contentHeight + 16, 200) @@ -565,11 +568,7 @@ ApplicationWindow { placeholderText: ollie.activeSessionId ? "Message..." : "No session" enabled: ollie.activeSessionId !== "" wrapMode: TextEdit.Wrap - onTextChanged: { - // Auto-scroll to bottom as content grows - textCursor.position = text.length - } - Keys.onReturnPressed: { + Keys.onReturnPressed: function(event) { if (event.modifiers & Qt.ShiftModifier) { event.accepted = false } else {