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);