// Copyright (C) 2026 Danilo M. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. import QtQuick import "../.." // Engines are read-only: stopping either would take its web UI down with it. Column { id: page required property var ai spacing: 8 Text { width: page.width text: "Engines" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true } color: Theme.subtext } Repeater { model: page.ai.engines AiRow { required property var modelData width: page.width title: page.ai.labels[modelData.name] ?? modelData.name on: modelData.up busy: modelData.busy detail: { if (!modelData.up) return "Not running"; if (modelData.model === "") return modelData.name === "llama" ? "No model loaded" : "Running"; return (modelData.busy ? "Generating" : "Idle") + " · " + modelData.model; } } } Item { width: 1; height: 6 } Text { width: page.width text: "Apps" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true } color: Theme.subtext } Repeater { model: page.ai.apps AiRow { required property var modelData width: page.width title: page.ai.labels[modelData.name] ?? modelData.name on: modelData.running detail: { if (!modelData.running) return "Stopped"; if (modelData.detail === "") return "Running"; return "Running · " + (modelData.name === "fanfic" ? "pid " : "") + modelData.detail; } action: modelData.running ? "Stop" : page.ai.canStart(modelData) ? "Start" : "" danger: modelData.running onTriggered: modelData.running ? page.ai.stop(modelData) : page.ai.start(modelData) } } }