kate: simplify diff review to git-based actions
Remove complex DiffWidget detection and context menu injection. Add 'Review Staged Changes' and 'Review Unstaged Changes' to editor context menu when in a git repo. Uses git diff directly. -119 lines of code removed.
This commit is contained in:
parent
f822bf6c32
commit
83cae21957
|
|
@ -16,7 +16,6 @@
|
|||
#include <QKeyEvent>
|
||||
#include <QMainWindow>
|
||||
#include <QMenu>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QProcess>
|
||||
#include <QStatusBar>
|
||||
#include <QToolButton>
|
||||
|
|
@ -25,33 +24,6 @@
|
|||
|
||||
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<QPlainTextEdit *>();
|
||||
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)
|
||||
|
|
@ -207,10 +179,6 @@ OllieKateView::OllieKateView(OllieKatePlugin *plugin, KTextEditor::MainWindow *m
|
|||
|
||||
// Kate project plugin's built-in Git widget integration
|
||||
setupProjectGitWidget();
|
||||
|
||||
// Hook into widget additions for diff widget integration
|
||||
connect(mainWindow, &KTextEditor::MainWindow::widgetAdded,
|
||||
this, &OllieKateView::onWidgetAdded);
|
||||
}
|
||||
|
||||
OllieKateView::~OllieKateView()
|
||||
|
|
@ -447,6 +415,20 @@ void OllieKateView::setupContextMenu(KTextEditor::View *view)
|
|||
startAction->setObjectName(QStringLiteral("ollie_ctx_start"));
|
||||
connect(startAction, &QAction::triggered, this, &OllieKateView::startSession);
|
||||
|
||||
// Git diff review actions (available when in a git repo)
|
||||
QString baseDir = projectBaseDir();
|
||||
if (!baseDir.isEmpty()) {
|
||||
auto *reviewStagedAction = menu->addAction(QIcon::fromTheme(QStringLiteral("vcs-diff")),
|
||||
QStringLiteral("Ollie: Review Staged Changes"));
|
||||
reviewStagedAction->setObjectName(QStringLiteral("ollie_ctx_review_staged"));
|
||||
connect(reviewStagedAction, &QAction::triggered, this, &OllieKateView::reviewStagedChanges);
|
||||
|
||||
auto *reviewUnstagedAction = menu->addAction(QIcon::fromTheme(QStringLiteral("vcs-diff")),
|
||||
QStringLiteral("Ollie: Review Unstaged Changes"));
|
||||
reviewUnstagedAction->setObjectName(QStringLiteral("ollie_ctx_review_unstaged"));
|
||||
connect(reviewUnstagedAction, &QAction::triggered, this, &OllieKateView::reviewUnstagedChanges);
|
||||
}
|
||||
|
||||
if (!v->selection()) return;
|
||||
|
||||
auto *explainAction = menu->addAction(QIcon::fromTheme(QStringLiteral("help-contents")),
|
||||
|
|
@ -706,67 +688,6 @@ void OllieKateView::onProjectTreeContextMenu(const QPoint &pos)
|
|||
menu.exec(m_projectTreeView->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void OllieKateView::onWidgetAdded(QWidget *widget)
|
||||
{
|
||||
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();
|
||||
|
||||
qDebug() << "Ollie: widgetAdded:" << className << objName;
|
||||
|
||||
bool isDiffWidget = className.contains(QLatin1String("Diff"), Qt::CaseInsensitive) ||
|
||||
objName.contains(QLatin1String("diff"), Qt::CaseInsensitive) ||
|
||||
widget->metaObject()->indexOfMethod("shouldClose()") >= 0;
|
||||
|
||||
if (isDiffWidget) {
|
||||
qDebug() << "Ollie: detected DiffWidget, installing event filter on editors";
|
||||
|
||||
// Store the diff widget for later use
|
||||
m_currentDiffWidget = widget;
|
||||
|
||||
// Find DiffEditor children (QPlainTextEdit) and install event filter on them
|
||||
auto editors = widget->findChildren<QPlainTextEdit *>();
|
||||
qDebug() << "Ollie: found" << editors.size() << "QPlainTextEdit children";
|
||||
for (auto *editor : editors) {
|
||||
editor->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OllieKateView::onDiffWidgetContextMenu(QWidget *diffWidget, const QPoint &pos)
|
||||
{
|
||||
QMenu menu(diffWidget);
|
||||
|
||||
auto *reviewAction = menu.addAction(QIcon::fromTheme(QStringLiteral("document-preview")),
|
||||
QStringLiteral("Ollie: Review This Diff"));
|
||||
connect(reviewAction, &QAction::triggered, this, [this, diffWidget]() {
|
||||
reviewDiffFromWidget(diffWidget);
|
||||
});
|
||||
|
||||
menu.exec(diffWidget->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void OllieKateView::reviewDiffFromWidget(QWidget *diffWidget)
|
||||
{
|
||||
// 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")
|
||||
+ diff + QStringLiteral("\n```");
|
||||
m_9p->write(agentPath() + "/prompt", prompt.toUtf8());
|
||||
}
|
||||
|
||||
void OllieKateView::reviewStagedChanges()
|
||||
{
|
||||
QString baseDir = projectBaseDir();
|
||||
|
|
@ -996,46 +917,10 @@ void OllieKateView::setupGhostProvider()
|
|||
}
|
||||
}
|
||||
|
||||
// --- Event Filter (ghost text key handling + diff context menu) ---
|
||||
|
||||
// Helper to check if widget is inside a diff widget
|
||||
static bool isInsideDiffWidget(QWidget *widget, QWidget *diffWidget)
|
||||
{
|
||||
QWidget *parent = widget->parentWidget();
|
||||
while (parent) {
|
||||
if (parent == diffWidget) return true;
|
||||
parent = parent->parentWidget();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// --- Event Filter (ghost text key handling) ---
|
||||
|
||||
bool OllieKateView::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
// Handle context menu for diff editors (QPlainTextEdit inside DiffWidget)
|
||||
if (event->type() == QEvent::ContextMenu) {
|
||||
auto *editor = qobject_cast<QPlainTextEdit *>(obj);
|
||||
if (editor && m_currentDiffWidget && isInsideDiffWidget(editor, m_currentDiffWidget)) {
|
||||
auto *contextEvent = static_cast<QContextMenuEvent *>(event);
|
||||
|
||||
// Create the standard context menu
|
||||
QMenu *menu = editor->createStandardContextMenu();
|
||||
|
||||
// Add separator and our action at the end
|
||||
menu->addSeparator();
|
||||
auto *reviewAction = menu->addAction(QIcon::fromTheme(QStringLiteral("document-preview")),
|
||||
QStringLiteral("Ollie: Review This Diff"));
|
||||
connect(reviewAction, &QAction::triggered, this, [this]() {
|
||||
if (m_currentDiffWidget) {
|
||||
reviewDiffFromWidget(m_currentDiffWidget);
|
||||
}
|
||||
});
|
||||
|
||||
menu->exec(contextEvent->globalPos());
|
||||
delete menu;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::KeyPress && m_ghost) {
|
||||
auto *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ protected:
|
|||
private slots:
|
||||
void onProjectChanged();
|
||||
void heartbeat();
|
||||
void onWidgetAdded(QWidget *widget);
|
||||
void onGitTreeContextMenu(const QPoint &pos);
|
||||
|
||||
public:
|
||||
|
|
@ -81,7 +80,6 @@ private:
|
|||
void reviewStagedChanges();
|
||||
void reviewUnstagedChanges();
|
||||
void askAboutGitSelection();
|
||||
void reviewDiffFromWidget(QWidget *diffWidget);
|
||||
|
||||
// Agent naming
|
||||
QString agentNameFromCwd(const QString &cwd);
|
||||
|
|
@ -99,7 +97,6 @@ private:
|
|||
void setupProjectTreeContextMenu();
|
||||
void setupGitPlusPlusDiffAction();
|
||||
void setupProjectGitWidget();
|
||||
void onDiffWidgetContextMenu(QWidget *diffWidget, const QPoint &pos);
|
||||
void onProjectTreeContextMenu(const QPoint &pos);
|
||||
|
||||
// Ghost text
|
||||
|
|
@ -121,7 +118,6 @@ private:
|
|||
// Git widget integration
|
||||
QPointer<QTreeView> m_gitTreeView;
|
||||
QPointer<QTreeView> m_projectTreeView;
|
||||
QPointer<QWidget> m_currentDiffWidget;
|
||||
};
|
||||
|
||||
#endif // OLLIE_KATE_PLUGIN_H
|
||||
|
|
|
|||
Loading…
Reference in New Issue