Commit a832a459 authored by Jan Blackquill's avatar Jan Blackquill 🌈
Browse files

applets/appmenu: Add search to global application menu

The global application menu has a new entry under Wayland titled "Search".
It allows searching and selecting menu items from the current application.
parent ae63802a
......@@ -10,6 +10,7 @@ target_link_libraries(appmenuplugin
Qt::Quick
KF5::Plasma
KF5::WindowSystem
KF5::I18n
PW::LibTaskManager
dbusmenuqt)
......
......@@ -30,6 +30,12 @@
#include <QGuiApplication>
#include <QMenu>
// Includes for the menu search.
#include <KLocalizedString>
#include <QLineEdit>
#include <QListView>
#include <QWidgetAction>
#include <abstracttasksmodel.h>
#include <dbusmenuimporter.h>
......@@ -88,6 +94,39 @@ AppMenuModel::AppMenuModel(QObject *parent)
emit modelNeedsUpdate();
}
});
// X11 has funky menu behaviour that prevents this from working properly.
if (KWindowSystem::isPlatformWayland()) {
m_searchAction = new QAction(this);
m_searchAction->setText(i18n("Search"));
m_searchAction->setObjectName(QStringLiteral("appmenu"));
m_searchMenu.reset(new QMenu);
auto searchAction = new QWidgetAction(this);
auto searchBar = new QLineEdit;
searchBar->setClearButtonEnabled(true);
searchBar->setPlaceholderText(i18n("Search..."));
searchBar->setMinimumWidth(200);
searchBar->setContentsMargins(4, 4, 4, 4);
connect(m_tasksModel, &TaskManager::TasksModel::activeTaskChanged, [=]() {
searchBar->setText(QString());
});
connect(searchBar, &QLineEdit::textChanged, [=]() mutable {
insertSearchActionsIntoMenu(searchBar->text());
});
connect(searchBar, &QLineEdit::returnPressed, [=]() mutable {
if (m_currentSearchActions.first()) {
m_currentSearchActions.first()->trigger();
}
});
connect(this, &AppMenuModel::modelNeedsUpdate, this, [this, searchBar]() mutable {
insertSearchActionsIntoMenu(searchBar->text());
});
searchAction->setDefaultWidget(searchBar);
m_searchMenu->addAction(searchAction);
m_searchMenu->addSeparator();
m_searchAction->setMenu(m_searchMenu.get());
}
}
AppMenuModel::~AppMenuModel() = default;
......@@ -136,7 +175,30 @@ int AppMenuModel::rowCount(const QModelIndex &parent) const
return 0;
}
return m_menu->actions().count();
return m_menu->actions().count()+(KWindowSystem::isPlatformWayland() ? 1 : 0);
}
void AppMenuModel::removeSearchActionsFromMenu()
{
for (const auto &action: m_currentSearchActions) {
m_searchAction->menu()->removeAction(action);
}
m_currentSearchActions = QList<QAction*>();
}
void AppMenuModel::insertSearchActionsIntoMenu(const QString &filter)
{
removeSearchActionsFromMenu();
if (filter.isEmpty()) {
return;
}
const auto actions = flatActionList();
for (const auto &action: actions) {
if (action->text().contains(filter, Qt::CaseInsensitive)) {
m_searchAction->menu()->addAction(action);
m_currentSearchActions << action;
}
}
}
void AppMenuModel::update()
......@@ -171,6 +233,21 @@ QHash<int, QByteArray> AppMenuModel::roleNames() const
return roleNames;
}
QList<QAction*> AppMenuModel::flatActionList()
{
QList<QAction*> ret;
if (!m_menuAvailable || !m_menu) {
return ret;
}
const auto actions = m_menu->findChildren<QAction*>();
for (auto &action: actions) {
if (action->menu() == nullptr) {
ret << action;
}
}
return ret;
}
QVariant AppMenuModel::data(const QModelIndex &index, int role) const
{
const int row = index.row();
......@@ -179,6 +256,13 @@ QVariant AppMenuModel::data(const QModelIndex &index, int role) const
}
const auto actions = m_menu->actions();
if (row == actions.count() && KWindowSystem::isPlatformWayland()) {
if (role == MenuRole) {
return m_searchAction->text();
} else if (role == ActionRole) {
return QVariant::fromValue((void*)m_searchAction);
}
}
if (row >= actions.count()) {
return QVariant();
}
......
......@@ -24,9 +24,12 @@
#include <KWindowSystem>
#include <QAbstractListModel>
#include <QAbstractListModel>
#include <QAction>
#include <QPointer>
#include <QRect>
#include <QStringList>
#include <QStringList>
#include <tasksmodel.h>
class QMenu;
......@@ -65,9 +68,11 @@ public:
QRect screenGeometry() const;
void setScreenGeometry(QRect geometry);
QList<QAction*> flatActionList();
Q_SIGNALS:
void requestActivateIndex(int index);
void bringToFocus(int index);
private Q_SLOTS:
void onActiveWindowChanged();
......@@ -92,7 +97,13 @@ private:
//! window that its menu initialization may be delayed
WId m_delayedMenuWindowId = 0;
QScopedPointer<QMenu> m_searchMenu;
QPointer<QMenu> m_menu;
QPointer<QAction> m_searchAction;
QList<QAction*> m_currentSearchActions;
void removeSearchActionsFromMenu();
void insertSearchActionsIntoMenu(const QString &filter = QString());
QDBusServiceWatcher *m_serviceWatcher;
QString m_serviceName;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment