radial: defer Ollie verb invocation to fix intermittent no-op
The Ollie slices only worked intermittently. onRadialActivated runs from RadialMenu::finishActivated(), which emits activatedId() while the radial popup (Qt::Popup) is still tearing down its grab/focus. The Ollie action methods read MainWindow::activeView() and the editor selection live; during that teardown window activeView() is transiently null (and selection unreadable), so a synchronous invoke silently no-ops — intermittently, depending on timing. The Kate-action path is unaffected because QAction::trigger() does not depend on activeView() being valid at that instant. Defer the Ollie invoke to the next event-loop turn via QTimer::singleShot(0), after the popup has fully closed and the editor is active again. Guard the plugin view with QPointer in case it is unloaded before the deferred call runs.
This commit is contained in:
parent
f05ad9b654
commit
7de4f8b549
|
|
@ -21,6 +21,7 @@
|
|||
#include <QEvent>
|
||||
#include <QKeySequence>
|
||||
#include <QMouseEvent>
|
||||
#include <QPointer>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
#include <QWindow>
|
||||
|
|
@ -254,29 +255,45 @@ bool RadialView::triggerOllieVerb(const QString &actionId) const
|
|||
}
|
||||
const QString verb = actionId.mid(QStringLiteral("ollie:").size());
|
||||
|
||||
// The selection-prompt verbs share one method with an argument; the rest are
|
||||
// zero-argument methods matching the Q_INVOKABLE names on the Ollie view.
|
||||
if (verb == QLatin1String("fix")) {
|
||||
QMetaObject::invokeMethod(view, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Fix")));
|
||||
} else if (verb == QLatin1String("refactor")) {
|
||||
QMetaObject::invokeMethod(view, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Refactor")));
|
||||
} else if (verb == QLatin1String("test")) {
|
||||
QMetaObject::invokeMethod(view, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Write unit tests for")));
|
||||
} else if (verb == QLatin1String("doc")) {
|
||||
QMetaObject::invokeMethod(view, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Add documentation comments to")));
|
||||
} else if (verb == QLatin1String("ask")) {
|
||||
QMetaObject::invokeMethod(view, "askAboutFile");
|
||||
} else if (verb == QLatin1String("explain")) {
|
||||
QMetaObject::invokeMethod(view, "explainSelection");
|
||||
} else if (verb == QLatin1String("verbatim")) {
|
||||
QMetaObject::invokeMethod(view, "sendVerbatim");
|
||||
} else if (verb == QLatin1String("start")) {
|
||||
QMetaObject::invokeMethod(view, "startSession");
|
||||
}
|
||||
// Defer the invocation to the next event-loop turn. We are called from
|
||||
// RadialMenu::finishActivated(), which emits activatedId() while the radial
|
||||
// (a Qt::Popup) is still tearing down its popup grab/focus. During that
|
||||
// window MainWindow::activeView() can be transiently null and the editor's
|
||||
// selection is not reliably readable — the Ollie actions read both live, so
|
||||
// invoking synchronously here makes them intermittently no-op. Running after
|
||||
// the popup has fully closed restores the active view and selection first.
|
||||
// (The Kate-action path does not need this: QAction::trigger() does not
|
||||
// depend on activeView() being valid at that instant.) Guard the view with
|
||||
// QPointer in case the plugin is unloaded before the deferred call runs.
|
||||
QPointer<QObject> safeView = view;
|
||||
auto invoke = [safeView, verb]() {
|
||||
QObject *v = safeView;
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
if (verb == QLatin1String("fix")) {
|
||||
QMetaObject::invokeMethod(v, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Fix")));
|
||||
} else if (verb == QLatin1String("refactor")) {
|
||||
QMetaObject::invokeMethod(v, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Refactor")));
|
||||
} else if (verb == QLatin1String("test")) {
|
||||
QMetaObject::invokeMethod(v, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Write unit tests for")));
|
||||
} else if (verb == QLatin1String("doc")) {
|
||||
QMetaObject::invokeMethod(v, "submitSelectionPrompt",
|
||||
Q_ARG(QString, QStringLiteral("Add documentation comments to")));
|
||||
} else if (verb == QLatin1String("ask")) {
|
||||
QMetaObject::invokeMethod(v, "askAboutFile");
|
||||
} else if (verb == QLatin1String("explain")) {
|
||||
QMetaObject::invokeMethod(v, "explainSelection");
|
||||
} else if (verb == QLatin1String("verbatim")) {
|
||||
QMetaObject::invokeMethod(v, "sendVerbatim");
|
||||
} else if (verb == QLatin1String("start")) {
|
||||
QMetaObject::invokeMethod(v, "startSession");
|
||||
}
|
||||
};
|
||||
QTimer::singleShot(0, m_mainWindow->window(), invoke);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue