|
|
|
#include "globalshortcuts.h"
|
|
|
|
|
|
|
|
#include <QAction>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QQuickItem>
|
|
|
|
#include <QMetaMethod>
|
|
|
|
|
|
|
|
#include <KActionCollection>
|
|
|
|
#include <KGlobalAccel>
|
|
|
|
#include <KLocalizedString>
|
|
|
|
#include <KPluginMetaData>
|
|
|
|
|
|
|
|
#include <Plasma/Applet>
|
|
|
|
#include <Plasma/Containment>
|
|
|
|
|
|
|
|
|
|
|
|
namespace Latte {
|
|
|
|
|
|
|
|
GlobalShortcuts::GlobalShortcuts(QObject *parent)
|
|
|
|
: QObject(parent)
|
|
|
|
{
|
|
|
|
m_corona = qobject_cast<DockCorona *>(parent);
|
|
|
|
|
|
|
|
if (m_corona) {
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_hideDockTimer.setSingleShot(true);
|
|
|
|
m_hideDockTimer.setInterval(3000);
|
|
|
|
connect(&m_hideDockTimer, &QTimer::timeout, this, [this]() {
|
|
|
|
if (m_hideDock) {
|
|
|
|
m_hideDock->visibility()->setBlockHiding(false);
|
|
|
|
m_hideDock = nullptr;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobalShortcuts::~GlobalShortcuts()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void GlobalShortcuts::init()
|
|
|
|
{
|
|
|
|
KActionCollection *taskbarActions = new KActionCollection(m_corona);
|
|
|
|
|
|
|
|
//activate actions
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
const int entryNumber = i + 1;
|
|
|
|
const Qt::Key key = static_cast<Qt::Key>(Qt::Key_0 + (entryNumber % 10));
|
|
|
|
|
|
|
|
QAction *action = taskbarActions->addAction(QStringLiteral("activate task manager entry %1").arg(QString::number(entryNumber)));
|
|
|
|
action->setText(i18n("Activate Task Manager Entry %1", entryNumber));
|
|
|
|
KGlobalAccel::setGlobalShortcut(action, QKeySequence(Qt::META + key));
|
|
|
|
connect(action, &QAction::triggered, this, [this, i] {
|
|
|
|
// qDebug() << "meta action...";
|
|
|
|
activateTaskManagerEntry(i, static_cast<Qt::Key>(Qt::META));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
//new instance actions
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
const int entryNumber = i + 1;
|
|
|
|
const Qt::Key key = static_cast<Qt::Key>(Qt::Key_0 + (entryNumber % 10));
|
|
|
|
|
|
|
|
QAction *action = taskbarActions->addAction(QStringLiteral("new instance for task manager entry %1").arg(QString::number(entryNumber)));
|
|
|
|
action->setText(i18n("New Instance for Task Manager Entry %1", entryNumber));
|
|
|
|
KGlobalAccel::setGlobalShortcut(action, QKeySequence(Qt::META + Qt::CTRL + key));
|
|
|
|
connect(action, &QAction::triggered, this, [this, i] {
|
|
|
|
// qDebug() << "meta + ctrl + action...";
|
|
|
|
activateTaskManagerEntry(i, static_cast<Qt::Key>(Qt::CTRL));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
//show-hide the main dock in the primary screen
|
|
|
|
QAction *showAction = taskbarActions->addAction(QStringLiteral("show latte dock"));
|
|
|
|
showAction->setText(i18n("Show Latte Dock"));
|
|
|
|
KGlobalAccel::setGlobalShortcut(showAction, QKeySequence(Qt::META + '`'));
|
|
|
|
connect(showAction, &QAction::triggered, this, [this]() {
|
|
|
|
showDock();
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Activate launcher menu through dbus interface
|
|
|
|
void GlobalShortcuts::activateLauncherMenu()
|
|
|
|
{
|
|
|
|
for (auto it = m_corona->m_dockViews.constBegin(), end = m_corona->m_dockViews.constEnd(); it != end; ++it) {
|
|
|
|
const auto applets = it.key()->applets();
|
|
|
|
|
|
|
|
for (auto applet : applets) {
|
|
|
|
const auto provides = applet->kPackage().metadata().value(QStringLiteral("X-Plasma-Provides"));
|
|
|
|
|
|
|
|
if (provides.contains(QLatin1String("org.kde.plasma.launchermenu"))) {
|
|
|
|
emit applet->activated();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Activate task manager entry
|
|
|
|
void GlobalShortcuts::activateTaskManagerEntry(int index, Qt::Key modifier)
|
|
|
|
{
|
|
|
|
auto activateTaskManagerEntryOnContainment = [this](const Plasma::Containment * c, int index, Qt::Key modifier) {
|
|
|
|
const auto &applets = c->applets();
|
|
|
|
|
|
|
|
for (auto *applet : applets) {
|
|
|
|
const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides"));
|
|
|
|
|
|
|
|
if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) {
|
|
|
|
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
|
|
|
|
const auto &childItems = appletInterface->childItems();
|
|
|
|
|
|
|
|
if (childItems.isEmpty()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (QQuickItem *item : childItems) {
|
|
|
|
if (auto *metaObject = item->metaObject()) {
|
|
|
|
// not using QMetaObject::invokeMethod to avoid warnings when calling
|
|
|
|
// this on applets that don't have it or other child items since this
|
|
|
|
// is pretty much trial and error.
|
|
|
|
|
|
|
|
// Also, "var" arguments are treated as QVariant in QMetaObject
|
|
|
|
int methodIndex = modifier == static_cast<Qt::Key>(Qt::META) ?
|
|
|
|
metaObject->indexOfMethod("activateTaskAtIndex(QVariant)") :
|
|
|
|
metaObject->indexOfMethod("newInstanceForTaskAtIndex(QVariant)");
|
|
|
|
|
|
|
|
if (methodIndex == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMetaMethod method = metaObject->method(methodIndex);
|
|
|
|
|
|
|
|
if (method.invoke(item, Q_ARG(QVariant, index))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// To avoid overly complex configuration, we'll try to get the 90% usecase to work
|
|
|
|
// which is activating a task on the task manager on a panel on the primary screen.
|
|
|
|
for (auto it = m_corona->m_dockViews.constBegin(), end = m_corona->m_dockViews.constEnd(); it != end; ++it) {
|
|
|
|
if (it.value()->screen() != qGuiApp->primaryScreen()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (activateTaskManagerEntryOnContainment(it.key(), index, modifier)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we didn't find anything on primary, try all the panels
|
|
|
|
for (auto it = m_corona->m_dockViews.constBegin(), end = m_corona->m_dockViews.constEnd(); it != end; ++it) {
|
|
|
|
if (activateTaskManagerEntryOnContainment(it.key(), index, modifier)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! update badge for specific dock item
|
|
|
|
void GlobalShortcuts::updateDockItemBadge(QString identifier, QString value)
|
|
|
|
{
|
|
|
|
//qDebug() << "DBUS CALL ::: " << identifier << " - " << value;
|
|
|
|
auto updateBadgeForTaskInContainment = [this](const Plasma::Containment * c, QString identifier, QString value) {
|
|
|
|
const auto &applets = c->applets();
|
|
|
|
|
|
|
|
for (auto *applet : applets) {
|
|
|
|
KPluginMetaData meta = applet->kPackage().metadata();
|
|
|
|
|
|
|
|
if (meta.pluginId() == "org.kde.latte.plasmoid") {
|
|
|
|
|
|
|
|
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
|
|
|
|
const auto &childItems = appletInterface->childItems();
|
|
|
|
|
|
|
|
if (childItems.isEmpty()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (QQuickItem *item : childItems) {
|
|
|
|
if (auto *metaObject = item->metaObject()) {
|
|
|
|
// not using QMetaObject::invokeMethod to avoid warnings when calling
|
|
|
|
// this on applets that don't have it or other child items since this
|
|
|
|
// is pretty much trial and error.
|
|
|
|
// Also, "var" arguments are treated as QVariant in QMetaObject
|
|
|
|
|
|
|
|
int methodIndex = metaObject->indexOfMethod("updateBadge(QVariant,QVariant)");
|
|
|
|
|
|
|
|
if (methodIndex == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMetaMethod method = metaObject->method(methodIndex);
|
|
|
|
|
|
|
|
if (method.invoke(item, Q_ARG(QVariant, identifier), Q_ARG(QVariant, value))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// update badges in all Latte Tasks plasmoids
|
|
|
|
for (auto it = m_corona->m_dockViews.constBegin(), end = m_corona->m_dockViews.constEnd(); it != end; ++it) {
|
|
|
|
updateBadgeForTaskInContainment(it.key(), identifier, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GlobalShortcuts::showDock()
|
|
|
|
{
|
|
|
|
//qDebug() << "DBUS CALL ::: " << identifier << " - " << value;
|
|
|
|
auto containsLattePlasmoid = [this](const Plasma::Containment * c) {
|
|
|
|
const auto &applets = c->applets();
|
|
|
|
|
|
|
|
for (auto *applet : applets) {
|
|
|
|
KPluginMetaData meta = applet->kPackage().metadata();
|
|
|
|
|
|
|
|
if (meta.pluginId() == "org.kde.latte.plasmoid") {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// To avoid overly complex configuration, we'll try to get the 90% usecase to work
|
|
|
|
// which is activating a task on the task manager on a panel on the primary screen.
|
|
|
|
for (auto it = m_corona->m_dockViews.constBegin(), end = m_corona->m_dockViews.constEnd(); it != end; ++it) {
|
|
|
|
if (it.value()->screen() != qGuiApp->primaryScreen()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (containsLattePlasmoid(it.key())) {
|
|
|
|
m_hideDock = it.value();
|
|
|
|
m_hideDock->visibility()->setBlockHiding(true);
|
|
|
|
m_hideDockTimer.start();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we didn't find anything on primary, try all the panels
|
|
|
|
for (auto it = m_corona->m_dockViews.constBegin(), end = m_corona->m_dockViews.constEnd(); it != end; ++it) {
|
|
|
|
if (containsLattePlasmoid(it.key())) {
|
|
|
|
m_hideDock = it.value();
|
|
|
|
m_hideDock->visibility()->setBlockHiding(true);
|
|
|
|
m_hideDockTimer.start();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_globalshortcuts.cpp"
|