From b7451708982bccc1d841527e5265c71fa1ec3a67 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Thu, 8 Oct 2026 10:36:27 +0200 Subject: [PATCH] kate: add Ollie button to git tool view instead of context menu The GitWidget creates local QMenu objects that can't be intercepted. Instead, add a QToolButton with dropdown menu to the git tool view: - Review Staged Changes - Review Unstaged Changes - Explain Selected Files This approach doesn't require Kate source modification. --- kde/kate/ollie_kate.cpp | 97 ++++++++++++++++++++++++----------------- kde/kate/ollie_kate.h | 1 + 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/kde/kate/ollie_kate.cpp b/kde/kate/ollie_kate.cpp index f9fce72..51d58ec 100644 --- a/kde/kate/ollie_kate.cpp +++ b/kde/kate/ollie_kate.cpp @@ -9,8 +9,6 @@ #include #include -#include -#include #include #include #include @@ -20,6 +18,7 @@ #include #include #include +#include #include #include @@ -489,13 +488,41 @@ void OllieKateView::setupProjectGitWidget() m_gitTreeView = treeView; } - // Install event filter on the git tool view to intercept menus - gitToolView->installEventFilter(this); + // Add Ollie button to the git tool view's button row + // Find the layout and add our button + if (auto *layout = gitToolView->layout()) { + // Create a button for Ollie actions + auto *ollieBtn = new QToolButton(gitToolView); + ollieBtn->setObjectName(QStringLiteral("ollie_git_btn")); + ollieBtn->setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); + ollieBtn->setToolTip(QStringLiteral("Ollie AI Actions")); + ollieBtn->setPopupMode(QToolButton::InstantPopup); + ollieBtn->setAutoRaise(true); + + auto *menu = new QMenu(ollieBtn); + menu->addAction(QIcon::fromTheme(QStringLiteral("document-preview")), + QStringLiteral("Review Staged Changes"), + this, &OllieKateView::reviewStagedChanges); + menu->addAction(QIcon::fromTheme(QStringLiteral("document-preview")), + QStringLiteral("Review Unstaged Changes"), + this, &OllieKateView::reviewUnstagedChanges); + menu->addAction(QIcon::fromTheme(QStringLiteral("help-about")), + QStringLiteral("Explain Selected Files"), + this, &OllieKateView::askAboutGitSelection); + ollieBtn->setMenu(menu); + + // Try to insert at a reasonable position + if (auto *boxLayout = qobject_cast(layout)) { + boxLayout->insertWidget(0, ollieBtn); + } else { + layout->addWidget(ollieBtn); + } + } } void OllieKateView::onGitTreeContextMenu(const QPoint &) { - // Unused - left for API compatibility + // Unused - context menu integration not possible without Kate modification } void OllieKateView::onWidgetAdded(QWidget *widget) @@ -573,19 +600,34 @@ void OllieKateView::reviewStagedChanges() if (!git.waitForFinished(5000)) return; QByteArray diff = git.readAllStandardOutput(); - if (diff.trimmed().isEmpty()) { - // No staged changes, try unstaged - git.start(QStringLiteral("git"), {QStringLiteral("diff")}); - if (!git.waitForFinished(5000)) return; - diff = git.readAllStandardOutput(); - } - if (diff.trimmed().isEmpty()) return; ensureAgent(); if (m_agentId.isEmpty()) return; - QString prompt = QStringLiteral("Read-only task. Review the following diff. Do not edit files. Identify correctness bugs, regressions, security issues, missing tests, and maintainability concerns. For each finding, explain the impact and cite the relevant hunk. If there are no findings, say so explicitly.\n\n```diff\n") + QString prompt = QStringLiteral("Read-only task. Review the following staged diff. Do not edit files. Identify correctness bugs, regressions, security issues, missing tests, and maintainability concerns. For each finding, explain the impact and cite the relevant hunk. If there are no findings, say so explicitly.\n\n```diff\n") + + QString::fromUtf8(diff) + QStringLiteral("\n```"); + m_9p->write(agentPath() + "/prompt", prompt.toUtf8()); +} + +void OllieKateView::reviewUnstagedChanges() +{ + QString baseDir = projectBaseDir(); + if (baseDir.isEmpty()) return; + + // Get unstaged diff via git + QProcess git; + git.setWorkingDirectory(baseDir); + git.start(QStringLiteral("git"), {QStringLiteral("diff")}); + if (!git.waitForFinished(5000)) return; + + QByteArray diff = git.readAllStandardOutput(); + if (diff.trimmed().isEmpty()) return; + + ensureAgent(); + if (m_agentId.isEmpty()) return; + + QString prompt = QStringLiteral("Read-only task. Review the following unstaged diff. Do not edit files. Identify correctness bugs, regressions, security issues, missing tests, and maintainability concerns. For each finding, explain the impact and cite the relevant hunk. If there are no findings, say so explicitly.\n\n```diff\n") + QString::fromUtf8(diff) + QStringLiteral("\n```"); m_9p->write(agentPath() + "/prompt", prompt.toUtf8()); } @@ -775,37 +817,10 @@ void OllieKateView::setupGhostProvider() } } -// --- Event Filter (ghost text key handling + git widget context menu) --- +// --- Event Filter (ghost text key handling) --- bool OllieKateView::eventFilter(QObject *obj, QEvent *event) { - // Watch for menus being created in the git tool view area - if (event->type() == QEvent::ChildAdded) { - auto *childEvent = static_cast(event); - if (auto *menu = qobject_cast(childEvent->child())) { - // Connect to aboutToShow to add our items - connect(menu, &QMenu::aboutToShow, this, [this, menu]() { - // Only add if we haven't already - bool hasOllieAction = false; - for (auto *action : menu->actions()) { - if (action->text().startsWith(QStringLiteral("Ollie:"))) { - hasOllieAction = true; - break; - } - } - if (!hasOllieAction && menu->actions().count() > 0) { - menu->addSeparator(); - menu->addAction(QIcon::fromTheme(QStringLiteral("document-preview")), - QStringLiteral("Ollie: Review Staged Changes"), - this, &OllieKateView::reviewStagedChanges); - menu->addAction(QIcon::fromTheme(QStringLiteral("help-about")), - QStringLiteral("Ollie: Ask About Selection"), - this, &OllieKateView::askAboutGitSelection); - } - }, Qt::UniqueConnection); - } - } - if (event->type() == QEvent::KeyPress && m_ghost) { auto *keyEvent = static_cast(event); diff --git a/kde/kate/ollie_kate.h b/kde/kate/ollie_kate.h index 4dc17b0..68d3502 100644 --- a/kde/kate/ollie_kate.h +++ b/kde/kate/ollie_kate.h @@ -74,6 +74,7 @@ private: void reviewDiff(); void startSession(); void reviewStagedChanges(); + void reviewUnstagedChanges(); void askAboutGitSelection(); void reviewDiffFromWidget(QWidget *diffWidget);