plasmoid: inline session rename, cwd folder dialog, fix rename signal bug
- Double-click session name in list to rename inline (RET to confirm, ESC to cancel) - Double-click cwd heading to open folder picker and change working directory - Add setConfig() to QML D-Bus client - Fix capi.go: chat/state callbacks used stale sessID after rename - Makefile: kf5 target uses trap to always restore CMakeLists.txt
This commit is contained in:
parent
28ce943e45
commit
9701d8f67c
26
Makefile
26
Makefile
|
|
@ -21,11 +21,11 @@ daemon: lib
|
||||||
|
|
||||||
# Step 2b: Build using KF5/Qt5 (for Plasma 5.27)
|
# Step 2b: Build using KF5/Qt5 (for Plasma 5.27)
|
||||||
kf5: lib
|
kf5: lib
|
||||||
cp CMakeLists.txt CMakeLists.txt.kf6.bak
|
@cp CMakeLists.txt CMakeLists.txt.kf6.bak && \
|
||||||
cp CMakeLists-kf5.txt CMakeLists.txt
|
trap 'mv -f CMakeLists.txt.kf6.bak CMakeLists.txt' EXIT && \
|
||||||
cmake -B $(BUILD_DIR) -S . --fresh
|
cp CMakeLists-kf5.txt CMakeLists.txt && \
|
||||||
cmake --build $(BUILD_DIR)
|
cmake -B $(BUILD_DIR) -S . --fresh && \
|
||||||
mv CMakeLists.txt.kf6.bak CMakeLists.txt
|
cmake --build $(BUILD_DIR)
|
||||||
|
|
||||||
# Install the KF5 build
|
# Install the KF5 build
|
||||||
kf5-install: kf5
|
kf5-install: kf5
|
||||||
|
|
@ -46,15 +46,13 @@ kf5-install: kf5
|
||||||
/usr/lib/x86_64-linux-gnu/qt5/qml/org/ollie/private/
|
/usr/lib/x86_64-linux-gnu/qt5/qml/org/ollie/private/
|
||||||
sudo install -m644 plasmoid/plugin/qmldir \
|
sudo install -m644 plasmoid/plugin/qmldir \
|
||||||
/usr/lib/x86_64-linux-gnu/qt5/qml/org/ollie/private/
|
/usr/lib/x86_64-linux-gnu/qt5/qml/org/ollie/private/
|
||||||
# Plasmoid package (swap metadata + QML for Plasma 5)
|
# Plasmoid package (use temp copy to avoid clobbering source tree ownership)
|
||||||
cp plasmoid/metadata.json plasmoid/metadata.json.kf6.bak
|
cp -a plasmoid /tmp/ollie-plasmoid-kf5
|
||||||
cp plasmoid/contents/ui/main.qml plasmoid/contents/ui/main.qml.kf6.bak
|
cp plasmoid/metadata-kf5.json /tmp/ollie-plasmoid-kf5/metadata.json
|
||||||
cp plasmoid/metadata-kf5.json plasmoid/metadata.json
|
cp plasmoid/contents/ui/main-kf5.qml /tmp/ollie-plasmoid-kf5/contents/ui/main.qml
|
||||||
cp plasmoid/contents/ui/main-kf5.qml plasmoid/contents/ui/main.qml
|
kpackagetool5 -t Plasma/Applet -u /tmp/ollie-plasmoid-kf5/ 2>/dev/null || \
|
||||||
kpackagetool5 -t Plasma/Applet -u plasmoid/ 2>/dev/null || \
|
kpackagetool5 -t Plasma/Applet -i /tmp/ollie-plasmoid-kf5/
|
||||||
kpackagetool5 -t Plasma/Applet -i plasmoid/
|
$(RM) -r /tmp/ollie-plasmoid-kf5
|
||||||
mv plasmoid/metadata.json.kf6.bak plasmoid/metadata.json
|
|
||||||
mv plasmoid/contents/ui/main.qml.kf6.bak plasmoid/contents/ui/main.qml
|
|
||||||
# Dolphin service menus + helpers
|
# Dolphin service menus + helpers
|
||||||
mkdir -p ~/.local/share/kio/servicemenus
|
mkdir -p ~/.local/share/kio/servicemenus
|
||||||
install -m755 dolphin/ollie-actions.desktop ~/.local/share/kio/servicemenus/
|
install -m755 dolphin/ollie-actions.desktop ~/.local/share/kio/servicemenus/
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ func ollie_create_session(cwdC *C.char, backendC *C.char, modelC *C.char, agentC
|
||||||
sess.logMu.Unlock()
|
sess.logMu.Unlock()
|
||||||
|
|
||||||
if chatCB != nil {
|
if chatCB != nil {
|
||||||
cID := C.CString(sessID)
|
cID := C.CString(sess.id)
|
||||||
cText := C.CString(text)
|
cText := C.CString(text)
|
||||||
C.ollie_chat_cb_invoke(chatCB, cID, C.int64_t(offset), cText, C.int(len(text)))
|
C.ollie_chat_cb_invoke(chatCB, cID, C.int64_t(offset), cText, C.int(len(text)))
|
||||||
C.free(unsafe.Pointer(cID))
|
C.free(unsafe.Pointer(cID))
|
||||||
|
|
@ -225,7 +225,7 @@ func ollie_create_session(cwdC *C.char, backendC *C.char, modelC *C.char, agentC
|
||||||
}
|
}
|
||||||
current = next
|
current = next
|
||||||
if stateCB != nil {
|
if stateCB != nil {
|
||||||
cID := C.CString(sessID)
|
cID := C.CString(sess.id)
|
||||||
cState := C.CString(current)
|
cState := C.CString(current)
|
||||||
C.ollie_state_cb_invoke(stateCB, cID, cState)
|
C.ollie_state_cb_invoke(stateCB, cID, cState)
|
||||||
C.free(unsafe.Pointer(cID))
|
C.free(unsafe.Pointer(cID))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.15
|
import QtQuick.Layouts 1.15
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
import org.kde.plasma.plasmoid 2.0
|
import org.kde.plasma.plasmoid 2.0
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||||
|
|
@ -13,6 +14,17 @@ Item {
|
||||||
|
|
||||||
readonly property var dbus: Ollie.OllieDBusClient
|
readonly property var dbus: Ollie.OllieDBusClient
|
||||||
|
|
||||||
|
FileDialog {
|
||||||
|
id: folderDialog
|
||||||
|
title: "Choose working directory"
|
||||||
|
selectFolder: true
|
||||||
|
folder: dbus.activeCwd ? "file://" + dbus.activeCwd : shortcuts.home
|
||||||
|
onAccepted: {
|
||||||
|
var path = fileUrl.toString().replace("file://", "")
|
||||||
|
dbus.setConfig(dbus.activeSessionId, "cwd", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Plasmoid.status: dbus.sessions.length > 0
|
Plasmoid.status: dbus.sessions.length > 0
|
||||||
? PlasmaCore.Types.ActiveStatus
|
? PlasmaCore.Types.ActiveStatus
|
||||||
: PlasmaCore.Types.PassiveStatus
|
: PlasmaCore.Types.PassiveStatus
|
||||||
|
|
@ -90,6 +102,15 @@ Item {
|
||||||
text: dbus.activeCwd || "Ollie"
|
text: dbus.activeCwd || "Ollie"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onDoubleClicked: {
|
||||||
|
if (dbus.activeSessionId !== "") {
|
||||||
|
folderDialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlasmaComponents.ToolButton {
|
PlasmaComponents.ToolButton {
|
||||||
|
|
@ -111,9 +132,12 @@ Item {
|
||||||
model: dbus.sessions
|
model: dbus.sessions
|
||||||
|
|
||||||
delegate: ItemDelegate {
|
delegate: ItemDelegate {
|
||||||
|
id: sessionDelegate
|
||||||
width: sessionList.width
|
width: sessionList.width
|
||||||
highlighted: modelData.id === dbus.activeSessionId
|
highlighted: modelData.id === dbus.activeSessionId
|
||||||
|
|
||||||
|
property bool renaming: false
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
spacing: 6
|
spacing: 6
|
||||||
|
|
||||||
|
|
@ -131,27 +155,60 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
id: sessionLabel
|
||||||
text: modelData.id
|
text: modelData.id
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.family: "monospace"
|
font.family: "monospace"
|
||||||
font.pixelSize: 11
|
font.pixelSize: 11
|
||||||
|
visible: !sessionDelegate.renaming
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: inlineRenameField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.family: "monospace"
|
||||||
|
font.pixelSize: 11
|
||||||
|
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 {
|
Label {
|
||||||
text: modelData.agent
|
text: modelData.agent
|
||||||
opacity: 0.7
|
opacity: 0.7
|
||||||
font.pixelSize: 11
|
font.pixelSize: 11
|
||||||
|
visible: !sessionDelegate.renaming
|
||||||
}
|
}
|
||||||
|
|
||||||
PlasmaComponents.ToolButton {
|
PlasmaComponents.ToolButton {
|
||||||
icon.name: "process-stop"
|
icon.name: "process-stop"
|
||||||
implicitWidth: 22; implicitHeight: 22
|
implicitWidth: 22; implicitHeight: 22
|
||||||
onClicked: dbus.killSession(modelData.id)
|
onClicked: dbus.killSession(modelData.id)
|
||||||
|
visible: !sessionDelegate.renaming
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: dbus.activeSessionId = modelData.id
|
onClicked: dbus.activeSessionId = modelData.id
|
||||||
|
onDoubleClicked: sessionDelegate.renaming = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Dialogs
|
||||||
import org.kde.plasma.plasmoid
|
import org.kde.plasma.plasmoid
|
||||||
import org.kde.plasma.components as PlasmaComponents
|
import org.kde.plasma.components as PlasmaComponents
|
||||||
import org.kde.plasma.extras as PlasmaExtras
|
import org.kde.plasma.extras as PlasmaExtras
|
||||||
|
|
@ -13,6 +14,16 @@ PlasmoidItem {
|
||||||
// Convenience alias
|
// Convenience alias
|
||||||
readonly property var dbus: Ollie.OllieDBusClient
|
readonly property var dbus: Ollie.OllieDBusClient
|
||||||
|
|
||||||
|
FolderDialog {
|
||||||
|
id: folderDialog
|
||||||
|
title: "Choose working directory"
|
||||||
|
currentFolder: dbus.activeCwd ? "file://" + dbus.activeCwd : StandardPaths.writableLocation(StandardPaths.HomeLocation)
|
||||||
|
onAccepted: {
|
||||||
|
let path = selectedFolder.toString().replace("file://", "")
|
||||||
|
dbus.setConfig(dbus.activeSessionId, "cwd", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
preferredRepresentation: compactRepresentation
|
preferredRepresentation: compactRepresentation
|
||||||
|
|
||||||
toolTipMainText: "Ollie"
|
toolTipMainText: "Ollie"
|
||||||
|
|
@ -88,6 +99,15 @@ PlasmoidItem {
|
||||||
text: dbus.activeCwd || "Ollie"
|
text: dbus.activeCwd || "Ollie"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onDoubleClicked: {
|
||||||
|
if (dbus.activeSessionId !== "") {
|
||||||
|
folderDialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlasmaComponents.ToolButton {
|
PlasmaComponents.ToolButton {
|
||||||
|
|
@ -109,9 +129,12 @@ PlasmoidItem {
|
||||||
model: dbus.sessions
|
model: dbus.sessions
|
||||||
|
|
||||||
delegate: ItemDelegate {
|
delegate: ItemDelegate {
|
||||||
|
id: sessionDelegate
|
||||||
width: sessionList.width
|
width: sessionList.width
|
||||||
highlighted: modelData.id === dbus.activeSessionId
|
highlighted: modelData.id === dbus.activeSessionId
|
||||||
|
|
||||||
|
property bool renaming: false
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
spacing: 6
|
spacing: 6
|
||||||
|
|
||||||
|
|
@ -129,27 +152,60 @@ PlasmoidItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
id: sessionLabel
|
||||||
text: modelData.id
|
text: modelData.id
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.family: "monospace"
|
font.family: "monospace"
|
||||||
font.pixelSize: 11
|
font.pixelSize: 11
|
||||||
|
visible: !sessionDelegate.renaming
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: inlineRenameField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.family: "monospace"
|
||||||
|
font.pixelSize: 11
|
||||||
|
visible: sessionDelegate.renaming
|
||||||
|
onAccepted: {
|
||||||
|
let 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 {
|
Label {
|
||||||
text: modelData.agent
|
text: modelData.agent
|
||||||
opacity: 0.7
|
opacity: 0.7
|
||||||
font.pixelSize: 11
|
font.pixelSize: 11
|
||||||
|
visible: !sessionDelegate.renaming
|
||||||
}
|
}
|
||||||
|
|
||||||
PlasmaComponents.ToolButton {
|
PlasmaComponents.ToolButton {
|
||||||
icon.name: "process-stop"
|
icon.name: "process-stop"
|
||||||
implicitWidth: 22; implicitHeight: 22
|
implicitWidth: 22; implicitHeight: 22
|
||||||
onClicked: dbus.killSession(modelData.id)
|
onClicked: dbus.killSession(modelData.id)
|
||||||
|
visible: !sessionDelegate.renaming
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: dbus.activeSessionId = modelData.id
|
onClicked: dbus.activeSessionId = modelData.id
|
||||||
|
onDoubleClicked: sessionDelegate.renaming = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,33 @@ bool OllieDBusClient::killSession(const QString &sessionId)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OllieDBusClient::renameSession(const QString &sessionId, const QString &newName)
|
||||||
|
{
|
||||||
|
QDBusReply<bool> reply = m_iface->call("RenameSession", sessionId, newName);
|
||||||
|
if (reply.isValid() && reply.value()) {
|
||||||
|
if (sessionId == m_activeSessionId) {
|
||||||
|
m_activeSessionId = newName;
|
||||||
|
emit activeSessionIdChanged();
|
||||||
|
}
|
||||||
|
refreshSessions();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OllieDBusClient::setConfig(const QString &sessionId, const QString &key, const QString &value)
|
||||||
|
{
|
||||||
|
QDBusReply<bool> reply = m_iface->call("SetConfig", sessionId, key, value);
|
||||||
|
if (reply.isValid() && reply.value()) {
|
||||||
|
if (sessionId == m_activeSessionId && key == "cwd") {
|
||||||
|
m_activeCwd = value;
|
||||||
|
emit activeCwdChanged();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool OllieDBusClient::submit(const QString &sessionId, const QString &prompt)
|
bool OllieDBusClient::submit(const QString &sessionId, const QString &prompt)
|
||||||
{
|
{
|
||||||
QDBusReply<bool> reply = m_iface->call("Submit", sessionId, prompt);
|
QDBusReply<bool> reply = m_iface->call("Submit", sessionId, prompt);
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ public:
|
||||||
Q_INVOKABLE void fetchChat();
|
Q_INVOKABLE void fetchChat();
|
||||||
Q_INVOKABLE QString createSession(const QString &cwd);
|
Q_INVOKABLE QString createSession(const QString &cwd);
|
||||||
Q_INVOKABLE bool killSession(const QString &sessionId);
|
Q_INVOKABLE bool killSession(const QString &sessionId);
|
||||||
|
Q_INVOKABLE bool renameSession(const QString &sessionId, const QString &newName);
|
||||||
|
Q_INVOKABLE bool setConfig(const QString &sessionId, const QString &key, const QString &value);
|
||||||
Q_INVOKABLE bool submit(const QString &sessionId, const QString &prompt);
|
Q_INVOKABLE bool submit(const QString &sessionId, const QString &prompt);
|
||||||
Q_INVOKABLE bool interrupt(const QString &sessionId);
|
Q_INVOKABLE bool interrupt(const QString &sessionId);
|
||||||
|
|
||||||
|
|
|
||||||
Reference in New Issue