/* * SPDX-License-Identifier: LGPL-2.0-or-later */ #include "ollieplugin.h" #include "palettewidget.h" #include #include #include #include #include #include #include #include #include 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> &out) const { KXMLGUIFactory *factory = m_mainWindow->guiFactory(); if (!factory) { return; } const QList clients = factory->clients(); for (KXMLGUIClient *client : clients) { KActionCollection *coll = client->actionCollection(); if (!coll) { continue; } const QList 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 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 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();) #include "ollieplugin.moc"