diff --git a/kde/kate/ollie_kate.cpp b/kde/kate/ollie_kate.cpp index 277900e..04ae7de 100644 --- a/kde/kate/ollie_kate.cpp +++ b/kde/kate/ollie_kate.cpp @@ -25,6 +25,33 @@ K_PLUGIN_CLASS_WITH_JSON(OllieKatePlugin, "metadata.json") +// Helper: detect if text looks like a unified diff +static bool looksLikeDiff(const QString &text) +{ + if (text.isEmpty()) return false; + // Check for unified diff markers + return text.contains(QLatin1String("diff --git")) || + text.contains(QLatin1String("@@ ")) || + text.contains(QLatin1String("--- a/")) || + text.contains(QLatin1String("+++ b/")) || + (text.contains(QLatin1String("---")) && text.contains(QLatin1String("+++"))); +} + +// Helper: extract diff content from a widget tree (for Kate's DiffWidget) +static QString extractDiffFromWidget(QWidget *widget) +{ + // Kate's DiffWidget uses DiffEditor (QPlainTextEdit subclass) children + // In Raw/Unified mode, one editor contains the actual diff + auto editors = widget->findChildren(); + for (auto *editor : editors) { + QString text = editor->toPlainText(); + if (looksLikeDiff(text)) { + return text; + } + } + return QString(); +} + // --- Plugin --- OllieKatePlugin::OllieKatePlugin(QObject *parent, const KPluginMetaData &data, const QVariantList &args) @@ -681,10 +708,20 @@ void OllieKateView::onProjectTreeContextMenu(const QPoint &pos) void OllieKateView::onWidgetAdded(QWidget *widget) { - // Check if this is a DiffWidget by looking for characteristic properties - // DiffWidget has a shouldClose() Q_INVOKABLE method - if (widget && widget->metaObject()->indexOfMethod("shouldClose()") >= 0) { - // This is likely a DiffWidget — install context menu handling + if (!widget) return; + + // Detect diff widgets by multiple heuristics: + // 1. Class name contains "Diff" + // 2. Has shouldClose() method (Kate's DiffWidget) + // 3. Object name contains "diff" + QString className = QString::fromLatin1(widget->metaObject()->className()); + QString objName = widget->objectName(); + bool isDiffWidget = className.contains(QLatin1String("Diff"), Qt::CaseInsensitive) || + objName.contains(QLatin1String("diff"), Qt::CaseInsensitive) || + widget->metaObject()->indexOfMethod("shouldClose()") >= 0; + + if (isDiffWidget) { + // Install context menu handling for diff review widget->setContextMenuPolicy(Qt::CustomContextMenu); connect(widget, &QWidget::customContextMenuRequested, this, [this, widget](const QPoint &pos) { @@ -708,37 +745,17 @@ void OllieKateView::onDiffWidgetContextMenu(QWidget *diffWidget, const QPoint &p void OllieKateView::reviewDiffFromWidget(QWidget *diffWidget) { - // Try to get the raw diff from the widget's m_rawDiff member - // DiffWidget stores the raw diff as a QByteArray - QByteArray diff; - - // Try reading the rawDiff property if exposed, otherwise get text from editors - QVariant rawDiffVar = diffWidget->property("rawDiff"); - if (rawDiffVar.isValid()) { - diff = rawDiffVar.toByteArray(); - } - - // If no rawDiff property, try to find the diff editors and get their text - if (diff.isEmpty()) { - auto editors = diffWidget->findChildren(); - for (auto *editor : editors) { - QString text = editor->toPlainText(); - if (text.contains(QLatin1String("diff --git")) || - text.contains(QLatin1String("@@")) || - text.contains(QLatin1String("--- a/"))) { - diff = text.toUtf8(); - break; - } - } - } - + // Extract diff content from Kate's DiffWidget + // DiffWidget uses DiffEditor (QPlainTextEdit) children to display diff + QString diff = extractDiffFromWidget(diffWidget); + if (diff.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::fromUtf8(diff) + QStringLiteral("\n```"); + + diff + QStringLiteral("\n```"); m_9p->write(agentPath() + "/prompt", prompt.toUtf8()); }