This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-kde/gui/main-kf5.qml

438 lines
15 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ApplicationWindow {
id: root
title: dbus.activeCwd ? "Ollie \u2014 " + dbus.activeCwd : "Ollie"
width: 900
height: 600
visible: true
color: palette.window
font.family: theme.fontFamily || Qt.application.font.family
font.pointSize: theme.fontSize > 0 ? theme.fontSize : Qt.application.font.pointSize
palette {
window: theme.windowColor
windowText: theme.windowTextColor
base: theme.baseColor
alternateBase: theme.alternateBaseColor
text: theme.textColor
button: theme.buttonColor
buttonText: theme.buttonTextColor
highlight: theme.highlightColor
highlightedText: theme.highlightedTextColor
toolTipBase: theme.tooltipBaseColor
toolTipText: theme.tooltipTextColor
link: theme.linkColor
mid: theme.midColor
dark: theme.darkColor
light: theme.lightColor
shadow: theme.shadowColor
}
// --- Settings Dialog ---
Dialog {
id: settingsDialog
title: "Settings"
anchors.centerIn: parent
width: 380
modal: true
standardButtons: Dialog.Close
contentItem: ColumnLayout {
spacing: 16
Label {
text: "Color Scheme"
font.bold: true
}
Label {
text: "Uses KDE Breeze color schemes"
opacity: 0.6
wrapMode: Text.Wrap
Layout.fillWidth: true
font.pixelSize: Qt.application.font.pixelSize * 0.9
}
ColumnLayout {
spacing: 8
RadioButton {
text: "Use system theme"
checked: theme.mode === "system"
onClicked: theme.mode = "system"
}
RadioButton {
text: "Breeze Light"
checked: theme.mode === "light"
onClicked: theme.mode = "light"
}
RadioButton {
text: "Breeze Dark"
checked: theme.mode === "dark"
onClicked: theme.mode = "dark"
}
}
Label {
text: theme.isDark ? "Current: dark" : "Current: light"
opacity: 0.5
font.pixelSize: Qt.application.font.pixelSize * 0.85
}
// --- Font section ---
Rectangle {
Layout.fillWidth: true
height: 1
color: palette.mid
Layout.topMargin: 8
}
Label {
text: "Font"
font.bold: true
}
GridLayout {
columns: 2
columnSpacing: 12
rowSpacing: 8
Layout.fillWidth: true
Label { text: "Family:" }
ComboBox {
id: fontFamilyCombo
Layout.fillWidth: true
model: theme.availableFamilies
editable: true
currentIndex: {
var fam = theme.fontFamily || Qt.application.font.family
var idx = model.indexOf(fam)
return idx >= 0 ? idx : 0
}
onActivated: theme.fontFamily = currentText
onAccepted: theme.fontFamily = editText
}
Label { text: "Style:" }
ComboBox {
id: fontStyleCombo
Layout.fillWidth: true
model: theme.availableStyles
currentIndex: {
var st = theme.fontStyle
var idx = model.indexOf(st)
return idx >= 0 ? idx : 0
}
onActivated: theme.fontStyle = currentText
}
Label { text: "Size:" }
SpinBox {
id: fontSizeSpin
from: 6
to: 72
value: theme.fontSize > 0 ? theme.fontSize : Qt.application.font.pointSize
onValueModified: theme.fontSize = value
}
}
Button {
text: "Reset to system font"
onClicked: theme.resetFont()
}
}
}
function openNewSessionDialog() {
var path = theme.chooseFolder("Choose working directory for new session")
if (path !== "")
dbus.createSession(path)
}
function openCwdDialog() {
var path = theme.chooseFolder("Change working directory",
dbus.activeCwd || "")
if (path !== "")
dbus.setConfig(dbus.activeSessionId, "cwd", path)
}
SplitView {
anchors.fill: parent
orientation: Qt.Horizontal
// --- Session sidebar ---
Pane {
SplitView.preferredWidth: 220
SplitView.minimumWidth: 160
padding: 0
ColumnLayout {
anchors.fill: parent
spacing: 0
// Toolbar
RowLayout {
Layout.fillWidth: true
Layout.margins: 6
Label {
text: "Sessions"
font.bold: true
Layout.fillWidth: true
}
ToolButton {
icon.name: "list-add"
onClicked: root.openNewSessionDialog()
ToolTip.text: "New session"
ToolTip.visible: hovered
}
ToolButton {
icon.name: "configure"
onClicked: settingsDialog.open()
ToolTip.text: "Settings"
ToolTip.visible: hovered
}
}
// Session list
ListView {
id: sessionList
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
model: dbus.sessions
delegate: ItemDelegate {
id: sessionDelegate
width: sessionList.width
highlighted: modelData.id === dbus.activeSessionId
property bool renaming: false
background: Rectangle {
color: sessionDelegate.highlighted
? palette.highlight : "transparent"
radius: 4
}
contentItem: RowLayout {
spacing: 6
Rectangle {
width: 8
height: 8
radius: 4
color: {
var state = modelData.state
if (state === "idle") return "#4caf50"
if (state.startsWith("calling")) return "#ff9800"
return "#2196f3"
}
}
Label {
id: sessionLabel
text: modelData.id
Layout.fillWidth: true
elide: Text.ElideRight
font.family: "monospace"
color: sessionDelegate.highlighted
? palette.highlightedText : palette.text
visible: !sessionDelegate.renaming
}
TextField {
id: renameField
Layout.fillWidth: true
font.family: "monospace"
visible: sessionDelegate.renaming
onAccepted: {
var newName = text.trim()
if (newName !== "" && newName !== modelData.id) {
dbus.renameSession(modelData.id, newName)
}
sessionDelegate.renaming = false
}
Keys.onEscapePressed: sessionDelegate.renaming = false
onVisibleChanged: {
if (visible) {
text = modelData.id
selectAll()
forceActiveFocus()
}
}
onActiveFocusChanged: {
if (!activeFocus && sessionDelegate.renaming) {
sessionDelegate.renaming = false
}
}
}
Label {
text: modelData.agent
opacity: 0.6
font.pixelSize: Qt.application.font.pixelSize * 0.85
color: sessionDelegate.highlighted
? palette.highlightedText : palette.text
visible: !sessionDelegate.renaming
}
ToolButton {
icon.name: "process-stop"
implicitWidth: 24
implicitHeight: 24
visible: !sessionDelegate.renaming
onClicked: dbus.killSession(modelData.id)
ToolTip.text: "Kill session"
ToolTip.visible: hovered
}
}
onClicked: dbus.activeSessionId = modelData.id
onDoubleClicked: sessionDelegate.renaming = true
}
}
}
}
// --- Main content ---
Pane {
SplitView.fillWidth: true
padding: 0
ColumnLayout {
anchors.fill: parent
spacing: 0
// Header bar
RowLayout {
Layout.fillWidth: true
Layout.margins: 8
Rectangle {
width: 10
height: 10
radius: 5
color: {
if (dbus.sessions.length === 0) return "gray"
var state = dbus.activeState
if (state === "idle") return "#4caf50"
if (state.startsWith("calling")) return "#ff9800"
return "#2196f3"
}
}
Label {
text: dbus.activeCwd || "No session selected"
Layout.fillWidth: true
elide: Text.ElideMiddle
font.bold: true
MouseArea {
anchors.fill: parent
onDoubleClicked: {
if (dbus.activeSessionId !== "") {
root.openCwdDialog()
}
}
}
}
Label {
text: dbus.activeState
opacity: 0.6
}
}
// Separator
Rectangle {
Layout.fillWidth: true
height: 1
color: palette.mid
}
// Chat view
ScrollView {
id: chatScroll
Layout.fillWidth: true
Layout.fillHeight: true
TextArea {
id: chatArea
readOnly: true
wrapMode: TextEdit.Wrap
text: dbus.chatText || (dbus.activeSessionId
? "(waiting for output...)"
: "Select or create a session")
font.family: "monospace"
color: dbus.chatText ? palette.text : theme.placeholderTextColor
background: null
onTextChanged: {
cursorPosition = text.length
}
}
}
// Separator
Rectangle {
Layout.fillWidth: true
height: 1
color: palette.mid
}
// Prompt input
RowLayout {
Layout.fillWidth: true
Layout.margins: 8
spacing: 6
TextField {
id: promptInput
Layout.fillWidth: true
placeholderText: dbus.activeSessionId
? "Message..."
: "No active session"
enabled: dbus.activeSessionId !== ""
onAccepted: {
if (text.trim() !== "" && dbus.activeSessionId !== "") {
dbus.submit(dbus.activeSessionId, text.trim())
text = ""
}
}
Component.onCompleted: forceActiveFocus()
}
ToolButton {
icon.name: "media-playback-stop"
enabled: dbus.activeState !== "idle" && dbus.activeSessionId !== ""
onClicked: dbus.interrupt(dbus.activeSessionId)
ToolTip.text: "Interrupt"
ToolTip.visible: hovered
}
}
// Status bar
Label {
Layout.fillWidth: true
Layout.leftMargin: 8
Layout.bottomMargin: 4
font.pixelSize: Qt.application.font.pixelSize * 0.85
opacity: 0.5
text: {
var id = dbus.activeSessionId
if (!id) return "ollie"
return dbus.activeState + " \u2502 " + id
}
}
}
}
}
}