161 lines
6.1 KiB
C++
161 lines
6.1 KiB
C++
/*
|
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*
|
|
* The Ollie command-palette plugin for Kate / KTextEditor.
|
|
*
|
|
* OlliePlugin is the KTextEditor::Plugin entry point. For every MainWindow the
|
|
* host creates an OllieView, which registers the "Command Palette (M-x)" action
|
|
* (Alt+X) and, when triggered, gathers every QAction currently exposed by the
|
|
* window's GUI clients into a PaletteWidget for orderless fuzzy selection.
|
|
*/
|
|
#ifndef KATECUSTOM_OLLIEPLUGIN_H
|
|
#define KATECUSTOM_OLLIEPLUGIN_H
|
|
|
|
#include <KTextEditor/Plugin>
|
|
|
|
#include "frecencystore.h"
|
|
#include "kateprojectbridge.h"
|
|
#include "projectindexer.h"
|
|
#include "palettemodel.h" // PaletteItem
|
|
#include "waylandcursorwarp.h"
|
|
|
|
#include <QObject>
|
|
#include <QPointer>
|
|
#include <QHash>
|
|
#include <QList>
|
|
|
|
class QAction;
|
|
class QKeyEvent;
|
|
|
|
namespace KTextEditor
|
|
{
|
|
class MainWindow;
|
|
class View;
|
|
}
|
|
|
|
namespace katecustom
|
|
{
|
|
|
|
class PaletteWidget;
|
|
class RadialMenu;
|
|
class OllieCommands;
|
|
struct RadialDef;
|
|
|
|
class OlliePlugin : public KTextEditor::Plugin
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit OlliePlugin(QObject *parent, const QVariantList &args = {});
|
|
~OlliePlugin() override;
|
|
|
|
QObject *createView(KTextEditor::MainWindow *mainWindow) override;
|
|
|
|
private:
|
|
OllieCommands *m_commands = nullptr; // ":"-verb pack, registered once globally
|
|
};
|
|
|
|
class OllieView : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
OllieView(OlliePlugin *plugin, KTextEditor::MainWindow *mainWindow);
|
|
~OllieView() override;
|
|
|
|
private Q_SLOTS:
|
|
void showCommandPalette();
|
|
void runAction(const QString &actionId);
|
|
void showFileSwitcher();
|
|
void openProjectFile(const QString &relativePath);
|
|
void showSymbolSwitcher();
|
|
void goToSymbol(const QString &locationId);
|
|
|
|
private:
|
|
// Record one activation of \a id and persist. Feeds the frecency bonus so
|
|
// habitual choices float up in every palette.
|
|
void recordUsage(const QString &id);
|
|
|
|
// The effective project root: Kate's loaded project (via the bridge) when
|
|
// available, otherwise derived from the active document's directory.
|
|
QString currentProjectRoot() const;
|
|
// Directory of the active document, or empty when none/untitled.
|
|
QString activeDocumentDir() const;
|
|
|
|
// Build palette items from raw index results (shared by the cache-hit and
|
|
// async-arrival paths). Root is used to project-qualify the frecency key.
|
|
QList<PaletteItem> buildFileItems(const QString &root, const QStringList &files) const;
|
|
QList<PaletteItem> buildSymbolItems(const QString &root, const QList<Symbol> &symbols) const;
|
|
|
|
// Size and place a palette: it spans the active window's width (minus a
|
|
// small margin), anchored near the top.
|
|
void positionPalette(PaletteWidget *palette);
|
|
|
|
// Move the OS pointer onto the center of the active view — used after a
|
|
// radial pane-focus action so the mouse follows the keyboard focus.
|
|
void warpCursorToActiveView();
|
|
// One harvested, runnable action with the provenance needed to build a
|
|
// unique id and to disambiguate labels shared by several commands.
|
|
struct ActionEntry {
|
|
QPointer<QAction> action;
|
|
QString label; // visible text, ampersands stripped
|
|
QString component; // owning collection's display name (provenance)
|
|
QString shortcut; // current shortcut, native text
|
|
QString id; // unique, stable key used on activation
|
|
};
|
|
|
|
// Collect every unique, enabled, visible QAction reachable from the
|
|
// window's GUI factory clients, deduplicated by pointer identity.
|
|
QList<ActionEntry> collectActions() const;
|
|
|
|
// Find a Kate action by its raw objectName across all GUI clients. Used to
|
|
// resolve radial-menu slice ids (which reference Kate action names).
|
|
QAction *findActionByName(const QString &objectName) const;
|
|
|
|
// Build the configured radials and bind each to its trigger key.
|
|
void setupRadials();
|
|
void showRadial(int defIndex); // centre on the caret
|
|
void showRadialAt(int defIndex, const QPoint &globalPos); // centre on a point
|
|
void onRadialActivated(const QString &actionId);
|
|
|
|
// Acme-style line-editing keys, handled in the event filter (no QActions,
|
|
// so there is nothing for Qt to report as an ambiguous shortcut).
|
|
void acmeBeginningOfLine(); // C-a
|
|
void acmeEndOfLine(); // C-e
|
|
void acmeEraseChar(); // C-h
|
|
void acmeEraseLine(); // C-u
|
|
void acmeEraseWord(); // C-w
|
|
// Dispatch an Acme key combo. Returns true if it was one of ours.
|
|
bool dispatchAcmeKey(QKeyEvent *ke);
|
|
|
|
// Catches configured mouse-button gestures inside the active view.
|
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
|
|
|
// On double-click adjacent to a bracket, select the text between the
|
|
// matching pair (multi-line aware). Returns true if a pair was selected.
|
|
bool selectBracketPairAt(KTextEditor::View *view, const QPoint &globalPos);
|
|
|
|
KTextEditor::MainWindow *m_mainWindow;
|
|
PaletteWidget *m_palette = nullptr;
|
|
PaletteWidget *m_filePalette = nullptr; // project "Go to File" switcher
|
|
QString m_fileSwitcherRoot; // project root for the open switcher
|
|
PaletteWidget *m_symbolPalette = nullptr; // project "Go to Symbol" switcher
|
|
QString m_symbolSwitcherRoot; // project root for the symbol switcher
|
|
RadialMenu *m_radial = nullptr;
|
|
QList<RadialDef> m_radialDefs;
|
|
QHash<int, int> m_buttonToRadial; // Qt::MouseButton (int) -> def index
|
|
bool m_gestureActive = false; // an RMB drag gesture is in progress
|
|
bool m_leftDownInView = false; // LMB held inside the view (Acme chord anchor)
|
|
bool m_swallowMiddleRelease = false; // swallow the release paired with a consumed middle press
|
|
bool m_swallowRightRelease = false; // swallow the release paired with a left+right paste chord
|
|
QHash<QString, QPointer<QAction>> m_actionsById;
|
|
FrecencyStore m_frecency; // persisted usage feeding the palette ranking
|
|
KateProjectBridge m_projectBridge; // read-only view of Kate's project plugin
|
|
ProjectIndexer m_indexer; // async, cached file/symbol indexing
|
|
WaylandCursorWarp m_cursorWarp; // pointer warp on Wayland (no-op on X11)
|
|
};
|
|
|
|
} // namespace katecustom
|
|
|
|
#endif
|