kate-deft/src/plugin/ollieplugin.cpp

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"