160 lines
4.7 KiB
C++
160 lines
4.7 KiB
C++
/*
|
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
#include "ollieplugin.h"
|
|
|
|
#include "palettewidget.h"
|
|
|
|
#include <KTextEditor/MainWindow>
|
|
|
|
#include <KActionCollection>
|
|
#include <KXMLGUIClient>
|
|
#include <KXMLGUIFactory>
|
|
#include <KLocalizedString>
|
|
#include <KPluginFactory>
|
|
|
|
#include <QAction>
|
|
#include <QKeySequence>
|
|
#include <QWidget>
|
|
|
|
namespace katecustom
|
|
{
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// OlliePlugin
|
|
// ---------------------------------------------------------------------------
|
|
|
|
OlliePlugin::OlliePlugin(QObject *parent, const QVariantList &args)
|
|
: KTextEditor::Plugin(parent)
|
|
{
|
|
Q_UNUSED(args);
|
|
}
|
|
|
|
OlliePlugin::~OlliePlugin() = default;
|
|
|
|
QObject *OlliePlugin::createView(KTextEditor::MainWindow *mainWindow)
|
|
{
|
|
return new OllieView(this, mainWindow);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// OllieView
|
|
// ---------------------------------------------------------------------------
|
|
|
|
OllieView::OllieView(OlliePlugin *plugin, KTextEditor::MainWindow *mainWindow)
|
|
: QObject(plugin)
|
|
, m_mainWindow(mainWindow)
|
|
{
|
|
// The one keyboard door: Alt+X (M-x). A single modifier, no chord, and the
|
|
// keys sit together on a compact layout.
|
|
auto *openAction = new QAction(i18n("Command Palette (M-x)"), this);
|
|
openAction->setObjectName(QStringLiteral("ollie_command_palette"));
|
|
openAction->setShortcut(QKeySequence(Qt::ALT | Qt::Key_X));
|
|
openAction->setShortcutContext(Qt::ApplicationShortcut);
|
|
connect(openAction, &QAction::triggered, this, &OllieView::showCommandPalette);
|
|
|
|
// Attach the shortcut to the window so it is always live.
|
|
if (QWidget *w = m_mainWindow->window()) {
|
|
w->addAction(openAction);
|
|
}
|
|
}
|
|
|
|
OllieView::~OllieView()
|
|
{
|
|
delete m_palette;
|
|
}
|
|
|
|
void OllieView::collectActions(QHash<QString, QPointer<QAction>> &out) const
|
|
{
|
|
KXMLGUIFactory *factory = m_mainWindow->guiFactory();
|
|
if (!factory) {
|
|
return;
|
|
}
|
|
|
|
const QList<KXMLGUIClient *> clients = factory->clients();
|
|
for (KXMLGUIClient *client : clients) {
|
|
KActionCollection *coll = client->actionCollection();
|
|
if (!coll) {
|
|
continue;
|
|
}
|
|
const QList<QAction *> actions = coll->actions();
|
|
for (QAction *action : actions) {
|
|
if (!action || action->isSeparator()) {
|
|
continue;
|
|
}
|
|
// Only offer things the user could actually invoke now.
|
|
if (!action->isEnabled() || !action->isVisible()) {
|
|
continue;
|
|
}
|
|
const QString label = action->text().remove(QLatin1Char('&')).trimmed();
|
|
if (label.isEmpty()) {
|
|
continue;
|
|
}
|
|
// Prefer the stable objectName as id; fall back to the label.
|
|
QString id = action->objectName();
|
|
if (id.isEmpty()) {
|
|
id = label;
|
|
}
|
|
if (!out.contains(id)) {
|
|
out.insert(id, action);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void OllieView::showCommandPalette()
|
|
{
|
|
if (!m_palette) {
|
|
m_palette = new PaletteWidget(m_mainWindow->window());
|
|
connect(m_palette, &PaletteWidget::activatedId, this, &OllieView::runAction);
|
|
}
|
|
|
|
m_actionsById.clear();
|
|
collectActions(m_actionsById);
|
|
|
|
QList<PaletteItem> items;
|
|
items.reserve(m_actionsById.size());
|
|
for (auto it = m_actionsById.cbegin(); it != m_actionsById.cend(); ++it) {
|
|
QAction *action = it.value();
|
|
if (!action) {
|
|
continue;
|
|
}
|
|
PaletteItem item;
|
|
item.id = it.key();
|
|
item.label = action->text().remove(QLatin1Char('&')).trimmed();
|
|
// Show the current shortcut as the group column hint, when present.
|
|
const QString sc = action->shortcut().toString(QKeySequence::NativeText);
|
|
item.group = sc;
|
|
items.push_back(item);
|
|
}
|
|
|
|
m_palette->setItems(items);
|
|
|
|
// Center the palette near the top of the active window.
|
|
if (QWidget *w = m_mainWindow->window()) {
|
|
const QSize sz = m_palette->size();
|
|
const QPoint topLeft = w->mapToGlobal(QPoint((w->width() - sz.width()) / 2,
|
|
w->height() / 6));
|
|
m_palette->move(topLeft);
|
|
}
|
|
|
|
m_palette->activate();
|
|
}
|
|
|
|
void OllieView::runAction(const QString &actionId)
|
|
{
|
|
QPointer<QAction> action = m_actionsById.value(actionId);
|
|
if (action) {
|
|
action->trigger();
|
|
}
|
|
}
|
|
|
|
} // namespace katecustom
|
|
|
|
// K_PLUGIN_FACTORY generates the factory and the moc-level registration. The
|
|
// matching .moc include is required in this translation unit.
|
|
K_PLUGIN_FACTORY_WITH_JSON(OlliePluginFactory, "ollieplugin.json",
|
|
registerPlugin<katecustom::OlliePlugin>();)
|
|
|
|
#include "ollieplugin.moc"
|