Skip to content

Commit

Permalink
feat: keyboard layout indicator support context menu
Browse files Browse the repository at this point in the history
linuxdeepin/developer-center#671

Change-Id: I751c48b4c00c9f75a9950b2679374b5562b08109
  • Loading branch information
listenerri committed Mar 6, 2019
1 parent f30e28c commit 89446d7
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 24 deletions.
143 changes: 130 additions & 13 deletions plugins/keyboard-layout/dbusadaptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,20 @@ DBusAdaptors::DBusAdaptors(QObject *parent)
: QDBusAbstractAdaptor(parent),
m_keyboard(new Keyboard("com.deepin.daemon.InputDevices",
"/com/deepin/daemon/InputDevice/Keyboard",
QDBusConnection::sessionBus(), this))
QDBusConnection::sessionBus(), this)),
m_menu(new QMenu())
{
connect(m_keyboard, &Keyboard::CurrentLayoutChanged, this, &DBusAdaptors::onLayoutChanged);
connect(m_keyboard, &Keyboard::UserLayoutListChanged, this, &DBusAdaptors::onLayoutChanged);
m_keyboard->setSync(false);

connect(m_keyboard, &Keyboard::CurrentLayoutChanged, this, &DBusAdaptors::onCurrentLayoutChanged);
connect(m_keyboard, &Keyboard::UserLayoutListChanged, this, &DBusAdaptors::onUserLayoutListChanged);

connect(m_menu, &QMenu::triggered, this, &DBusAdaptors::handleActionTriggered);

// init data
initAllLayoutList();
onCurrentLayoutChanged(m_keyboard->currentLayout());
onUserLayoutListChanged(m_keyboard->userLayoutList());
}

DBusAdaptors::~DBusAdaptors()
Expand All @@ -36,25 +46,132 @@ DBusAdaptors::~DBusAdaptors()

QString DBusAdaptors::layout() const
{
QStringList layouts = m_keyboard->userLayoutList();
if (layouts.size() < 2) {
if (m_userLayoutList.size() < 2) {
// do NOT show keyboard indicator
return QString();
}

QString currentLayout = m_keyboard->currentLayout().split(';').first();
if (!currentLayout.isEmpty())
return currentLayout;
if (m_currentLayout.isEmpty()) {
// refetch data
QTimer::singleShot(1000, m_keyboard, &Keyboard::currentLayout);
qWarning() << Q_FUNC_INFO << "currentLayout is Empty!!";
}

return m_currentLayout;
}

qWarning() << Q_FUNC_INFO << "currentLayout is Empty!!";
void DBusAdaptors::onClicked(int button, int x, int y)
{
// button value means(XCB_BUTTON_INDEX):
// 0, Any of the following (or none)
// 1, The left mouse button.
// 2, The right mouse button.
// 3, The middle mouse button.
// 4, Scroll wheel. TODO: direction?
// 5, Scroll wheel. TODO: direction?

// re-fetch data.
QTimer::singleShot(1000, this, &DBusAdaptors::onLayoutChanged);
Q_UNUSED(button);

return QString();
if (m_menu && m_userLayoutList.size() >= 2) {
m_menu->exec(QPoint(x, y));
}
}

void DBusAdaptors::onLayoutChanged()
void DBusAdaptors::onCurrentLayoutChanged(const QString &value)
{
m_currentLayoutRaw = value;
m_currentLayout = value.split(';').first();

refreshMenuSelection();

emit layoutChanged(layout());
}

void DBusAdaptors::onUserLayoutListChanged(const QStringList &value)
{
m_userLayoutList = value;

refreshMenu();
}

void DBusAdaptors::initAllLayoutList()
{
QDBusPendingCall call = m_keyboard->LayoutList();
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] {
if (call.isError()) {
qWarning() << "failed to get all keyboard list: " << call.error().message();
} else {
QDBusReply<KeyboardLayoutList> reply = call.reply();
m_allLayoutList = reply.value();
refreshMenu();
}

watcher->deleteLater();
});
}

void DBusAdaptors::refreshMenu()
{
if (!m_menu || m_userLayoutList.size() < 2) {
return;
}

// all action object will be deleted
m_menu->clear();

for (const QString &layoutRawName : m_userLayoutList) {
const QString layoutName = duplicateCheck(layoutRawName);
const QString layoutLocalizedName = m_allLayoutList.value(layoutRawName);
const QString text = QString("%1 (%2)").arg(layoutLocalizedName).arg(layoutName);

QAction *action = new QAction(text, m_menu);
action->setObjectName(layoutRawName);
action->setCheckable(true);
action->setChecked(layoutRawName == m_currentLayoutRaw);
m_menu->addAction(action);
}

m_menu->addSeparator();

// will be deleted after QMenu->clear() above
m_addLayoutAction = new QAction(tr("Add keyboard layout"), m_menu);

m_menu->addAction(m_addLayoutAction);
}

void DBusAdaptors::refreshMenuSelection()
{
for (QAction *action : m_menu->actions()) {
action->setChecked(action->objectName() == m_currentLayoutRaw);
}
}

void DBusAdaptors::handleActionTriggered(QAction *action)
{
if (action == m_addLayoutAction) {
QProcess::startDetached("dbus-send --print-reply --dest=com.deepin.dde.ControlCenter "
"/com/deepin/dde/ControlCenter "
"com.deepin.dde.ControlCenter.ShowModule string:keyboard");
}

const QString layout = action->objectName();
if (m_userLayoutList.contains(layout)) {
m_keyboard->setCurrentLayout(layout);
}
}

QString DBusAdaptors::duplicateCheck(const QString &kb)
{
QStringList list;
const QString kbFirst = kb.split(";").first();
for (const QString &data : m_userLayoutList) {
if (data.split(";").first() == kbFirst) {
list << data;
}
}

const QString kblayout = kb.split(";").first().mid(0, 2);

return kblayout + (list.count() > 1 ? QString::number(list.indexOf(kb) + 1) : "");
}
37 changes: 28 additions & 9 deletions plugins/keyboard-layout/dbusadaptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#ifndef DBUSADAPTORS_H
#define DBUSADAPTORS_H

#include <QMenu>
#include <QtDBus/QtDBus>
#include <com_deepin_daemon_inputdevice_keyboard.h>

Expand All @@ -29,14 +30,14 @@ class DBusAdaptors : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.deepin.dde.Keyboard")
Q_CLASSINFO("D-Bus Introspection", ""
" <interface name=\"com.deepin.dde.Keyboard\">\n"
" <property access=\"read\" type=\"s\" name=\"layout\"/>\n"
" <signal name=\"layoutChanged\">"
" <arg name=\"layout\" type=\"s\"/>"
" </signal>"
" </interface>\n"
"")
// Q_CLASSINFO("D-Bus Introspection", ""
// " <interface name=\"com.deepin.dde.Keyboard\">\n"
// " <property access=\"read\" type=\"s\" name=\"layout\"/>\n"
// " <signal name=\"layoutChanged\">"
// " <arg name=\"layout\" type=\"s\"/>"
// " </signal>"
// " </interface>\n"
// "")

public:
DBusAdaptors(QObject *parent = nullptr);
Expand All @@ -47,13 +48,31 @@ class DBusAdaptors : public QDBusAbstractAdaptor
QString layout() const;

public slots:
void onLayoutChanged();
void onClicked(int button, int x, int y);

signals:
void layoutChanged(QString text);

private slots:
void onCurrentLayoutChanged(const QString & value);
void onUserLayoutListChanged(const QStringList & value);
void initAllLayoutList();
void refreshMenu();
void refreshMenuSelection();
void handleActionTriggered(QAction *action);

private:
QString duplicateCheck(const QString &kb);

private:
Keyboard *m_keyboard;
QMenu *m_menu;
QAction *m_addLayoutAction;

QString m_currentLayoutRaw;
QString m_currentLayout;
QStringList m_userLayoutList;
KeyboardLayoutList m_allLayoutList;
};

#endif
8 changes: 8 additions & 0 deletions plugins/keyboard-layout/keybord_layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,13 @@
"dbus_interface": "com.deepin.dde.Keyboard",
"dbus_properties": "layout"
}
},
"action": {
"trigger": {
"dbus_service": "com.deepin.dde.Keyboard",
"dbus_path": "/com/deepin/dde/Keyboard",
"dbus_interface": "com.deepin.dde.Keyboard",
"dbus_method": "onClicked"
}
}
}
4 changes: 2 additions & 2 deletions plugins/tray/indicatortray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ void IndicatorTrayPrivate::initDBus(const QString &indicatorKey)

const QJsonObject action = config.value("action").toObject();
if (!action.isEmpty())
q->connect(indicatorTrayWidget, &IndicatorTrayWidget::clicked, q, [ = ](uint8_t /*button_index*/, int /*x*/, int /*y*/) {
q->connect(indicatorTrayWidget, &IndicatorTrayWidget::clicked, q, [ = ](uint8_t button_index, int x, int y) {
auto triggerConfig = action.value("trigger").toObject();
auto dbusService = triggerConfig.value("dbus_service").toString();
auto dbusPath = triggerConfig.value("dbus_path").toString();
Expand All @@ -185,7 +185,7 @@ void IndicatorTrayPrivate::initDBus(const QString &indicatorKey)
auto bus = isSystemBus ? QDBusConnection::systemBus() : QDBusConnection::sessionBus();

QDBusInterface interface(dbusService, dbusPath, dbusInterface, bus, q);
interface.asyncCall(methodName);
interface.asyncCall(methodName, button_index, x, y);
});
});
}
Expand Down

0 comments on commit 89446d7

Please sign in to comment.