ollie/kde/gui/main.qml

253 lines
8.4 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ApplicationWindow {
id: root
visible: true
width: 1000
height: 600
minimumWidth: 320
minimumHeight: 240
title: "Ollie"
font.family: theme.fontFamily || Qt.application.font.family
font.pointSize: theme.fontSize > 0 ? theme.fontSize : Qt.application.font.pointSize
// Apply theme palette to all Qt Quick Controls
palette.active.window: theme.windowColor
palette.active.windowText: theme.windowTextColor
palette.active.base: theme.baseColor
palette.active.text: theme.textColor
palette.active.button: theme.buttonColor
palette.active.buttonText: theme.buttonTextColor
palette.active.highlight: theme.highlightColor
palette.active.highlightedText: theme.highlightedTextColor
palette.active.mid: theme.midColor
palette.active.dark: theme.darkColor
palette.active.light: theme.lightColor
palette.active.shadow: theme.shadowColor
palette.active.link: theme.linkColor
palette.active.toolTipBase: theme.tooltipBaseColor
palette.active.toolTipText: theme.tooltipTextColor
palette.active.placeholderText: theme.placeholderTextColor
palette.active.alternateBase: theme.alternateBaseColor
palette.inactive.window: theme.windowColor
palette.inactive.windowText: theme.windowTextColor
palette.inactive.base: theme.baseColor
palette.inactive.text: theme.textColor
palette.inactive.button: theme.buttonColor
palette.inactive.buttonText: theme.buttonTextColor
palette.inactive.highlight: theme.highlightColor
palette.inactive.highlightedText: theme.highlightedTextColor
palette.inactive.mid: theme.midColor
palette.inactive.dark: theme.darkColor
palette.inactive.light: theme.lightColor
palette.inactive.shadow: theme.shadowColor
palette.inactive.link: theme.linkColor
palette.inactive.toolTipBase: theme.tooltipBaseColor
palette.inactive.toolTipText: theme.tooltipTextColor
palette.inactive.placeholderText: theme.placeholderTextColor
palette.inactive.alternateBase: theme.alternateBaseColor
palette.disabled.window: theme.windowColor
palette.disabled.windowText: theme.midColor
palette.disabled.base: theme.baseColor
palette.disabled.text: theme.midColor
palette.disabled.button: theme.buttonColor
palette.disabled.buttonText: theme.midColor
palette.disabled.highlight: theme.highlightColor
palette.disabled.highlightedText: theme.highlightedTextColor
palette.disabled.mid: theme.midColor
palette.disabled.dark: theme.darkColor
palette.disabled.light: theme.lightColor
palette.disabled.shadow: theme.shadowColor
Shortcut {
sequence: "Ctrl+B"
onActivated: root.sidebarVisible = !root.sidebarVisible
}
Shortcut {
sequence: "Escape"
onActivated: {
if (sessionTree.renamingIndex >= 0) {
sessionTree.cancelRename()
} else {
// Always send stop - server-side Interrupt() is safe to call
// on an idle agent (no-op). This avoids races where the GUI's
// cached activeState is stale.
ollie.interrupt()
}
}
}
// Bypass approval/denial shortcuts (configurable in Settings)
Shortcut {
sequence: theme.approveBypassKey
enabled: theme.approveBypassKey !== "" && chatPane.hasPendingBypass
onActivated: chatPane.approveBypass()
}
Shortcut {
sequence: theme.denyBypassKey
enabled: theme.denyBypassKey !== "" && chatPane.hasPendingBypass
onActivated: chatPane.denyBypass()
}
property bool sidebarVisible: true
property bool quitting: false
onClosing: function(close) {
if (!quitting && theme.closeToTray) {
close.accepted = false
root.hide()
trayIcon.show()
}
}
Dialog {
id: renameErrorDialog
title: "Rename Failed"
width: 320
modal: false
x: (parent ? (parent.width - width) / 2 : 0)
y: (parent ? (parent.height - height) / 2 : 0)
// Keep the non-modal dialog visually separate from the application behind it.
background: Item {
// A dark offset layer reads as a shadow instead of a bright outline.
Rectangle {
x: 4
y: 6
width: parent.width
height: parent.height
color: Qt.rgba(0, 0, 0, 0.28)
radius: 4
}
Rectangle {
anchors.fill: parent
color: theme.windowColor
border.color: theme.dialogOutlineColor
border.width: 3
radius: 4
Rectangle {
anchors.fill: parent
anchors.margins: 3
color: "transparent"
border.color: theme.lightColor
border.width: 1
radius: 3
}
}
}
header: Rectangle {
implicitHeight: 36
color: theme.buttonColor
Text { anchors.centerIn: parent; text: renameErrorDialog.title; color: theme.buttonTextColor }
MouseArea {
anchors.fill: parent
cursorShape: Qt.SizeAllCursor
property point pressPosition
onPressed: pressPosition = Qt.point(mouse.x, mouse.y)
onPositionChanged: if (pressed) {
renameErrorDialog.x += mouse.x - pressPosition.x
renameErrorDialog.y += mouse.y - pressPosition.y
}
}
}
standardButtons: Dialog.Ok
// Dialogs never request keyboard focus.
focus: false
property string itemType: "session"
property string attemptedName: ""
contentItem: Label {
text: "Could not rename " + renameErrorDialog.itemType + " to \"" + renameErrorDialog.attemptedName + "\".\n\nThe name may already be in use."
wrapMode: Text.Wrap
}
}
// --- Settings Dialog ---
SettingsDialog {
id: settingsDialog
}
// --- New Session Dialog ---
NewSessionDialog {
id: newSessionDialog
}
// --- New Agent Dialog ---
NewAgentDialog {
id: newAgentDialog
targetSessionId: ""
}
// --- Goal Dialog ---
GoalDialog {
id: goalDialog
}
// --- Process Manager Window ---
ProcManagerWindow {
id: procManagerWindow
visible: false
}
// --- Peer Manager Window ---
PeerManagerWindow {
id: peerManagerWindow
visible: false
}
SplitView {
anchors.fill: parent
SessionTree {
id: sessionTree
SplitView.preferredWidth: root.sidebarVisible ? root.width * 0.15 : 0
SplitView.minimumWidth: 0
visiblePane: root.sidebarVisible
onNewSessionRequested: {
newSessionDialog.editMode = false
newSessionDialog.editSessionName = ""
newSessionDialog.open()
}
onSettingsRequested: settingsDialog.open()
onSessionSettingsRequested: function(sessionName) {
newSessionDialog.openForSession(sessionName)
}
onNewAgentRequested: function(sessionId) {
newAgentDialog.editMode = false
newAgentDialog.editAgentId = ""
newAgentDialog.targetSessionId = sessionId
newAgentDialog.open()
}
onAgentSettingsRequested: function(sessionId, agentId) {
newAgentDialog.openForAgent(sessionId, agentId)
}
onGoalRequested: function(sessionId, sessionName) {
goalDialog.sessionId = sessionId
goalDialog.sessionName = sessionName
goalDialog.open()
}
onRenameFailed: function(itemType, attemptedName) {
renameErrorDialog.itemType = itemType
renameErrorDialog.attemptedName = attemptedName
renameErrorDialog.open()
}
}
ChatPane {
id: chatPane
SplitView.fillWidth: true
SplitView.fillHeight: true
sidebarVisible: root.sidebarVisible
onToggleSidebar: root.sidebarVisible = !root.sidebarVisible
}
}
}