Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/plugin-qt/shortcut/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ set(SHORTCUT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(SHORTCUT_COMMON_SOURCES
${SHORTCUT_SRC_DIR}/core/shortcutmanager.cpp
${SHORTCUT_SRC_DIR}/core/keybindingmanager.cpp
${SHORTCUT_SRC_DIR}/core/customshortcuttransaction.cpp
${SHORTCUT_SRC_DIR}/core/gesturemanager.cpp
${SHORTCUT_SRC_DIR}/core/qkeysequenceconverter.cpp
${SHORTCUT_SRC_DIR}/core/actionexecutor.cpp
${SHORTCUT_SRC_DIR}/core/translationmanager.cpp
${SHORTCUT_SRC_DIR}/config/configloader.cpp
${SHORTCUT_SRC_DIR}/config/customshortcutstore.cpp
${SHORTCUT_SRC_DIR}/backend/abstractkeyhandler.h
${SHORTCUT_SRC_DIR}/backend/abstractgesturehandler.h
${SHORTCUT_SRC_DIR}/backend/specialkeyhandler.cpp
Expand Down Expand Up @@ -113,6 +115,12 @@ foreach(SUBDIR_PATH ${SHORTCUT_CONFIG_SUBDIRS})
)
endforeach()

# install base json config
dtk_add_config_meta_files(
APPID "org.deepin.dde.keybinding"
FILES "${CMAKE_CURRENT_SOURCE_DIR}/configs/org.deepin.shortcut.json"
)

foreach(SUBDIR_PATH ${GESTURE_CONFIG_SUBDIRS})
dtk_add_config_meta_files(
APPID "org.deepin.dde.keybinding"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
"value": [
"Meta+P"
],
"serial": 0,
"serial": 1,
"flags": [],
"name": "hotkeys",
"name[zh_CN]": "快捷键组合",
"description": "切换显示模式快捷键组合",
"permissions": "",
"permissions": "readwrite",
"visibility": "private"
},
"triggerType": {
Expand Down
86 changes: 86 additions & 0 deletions src/plugin-qt/shortcut/configs/org.deepin.shortcut.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"magic": "dsg.config.meta",
"version": "1.0",
"contents": {
"appId": {
"value": "org.deepin.dde.keybinding",
"serial": 0,
"flags": [],
"name": "appId",
"name[zh_CN]": "提供快捷键应用Id",
"description": "provide shortcut app id",
"permissions": "readwrite",
"visibility": "private"
},
"displayName": {
"value": "",
"serial": 0,
"flags": [],
"name": "displayName",
"name[zh_CN]": "",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"hotkeys": {
"value": [],
"serial": 0,
"flags": [],
"name": "hotkeys",
"name[zh_CN]": "快捷键组合",
"description": "打开默认终端快捷键组合",
"permissions": "readwrite",
"visibility": "private"
},
"triggerType": {
"value": 1,
"serial": 0,
"flags": [],
"name": "triggerType",
"name[zh_CN]": "快捷键触发动作类型",
"description": "二进制command类型",
"permissions": "readwrite",
"visibility": "private"
},
"triggerValue": {
"value": [],
"serial": 0,
"flags": [],
"name": "triggerValue",
"name[zh_CN]": "快捷键触发动作",
"description": "",
"permissions": "readwrite",
"visibility": "private"
},
"category": {
"value": "Custom",
"serial": 1,
"flags": [],
"name": "category",
"name[zh_CN]": "快捷键类别(Custom)",
"description": "Custom shortcut category",
"permissions": "readwrite",
"visibility": "private"
},
"enabled": {
"value": true,
"serial": 0,
"flags": [],
"name": "enabled",
"name[zh_CN]": "使能",
"description": "是否启用快捷键",
"permissions": "readwrite",
"visibility": "private"
},
"modifiable": {
"value": true,
"serial": 0,
"flags": [],
"name": "modifiable",
"name[zh_CN]": "能否修改快捷键",
"description": "不能修改快捷键",
"permissions": "readwrite",
"visibility": "private"
}
}
}
183 changes: 157 additions & 26 deletions src/plugin-qt/shortcut/src/config/configloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "configloader.h"
#include "core/shortcutconfig.h"

#include <algorithm>

Check warning on line 7 in src/plugin-qt/shortcut/src/config/configloader.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <algorithm> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <QDir>
#include <QDebug>
Expand All @@ -24,6 +23,12 @@

DCORE_USE_NAMESPACE

static DConfig *createDConfig(const QString &name, const QString &subPath, QObject *parent)
{
const QString normalized = CustomShortcutStore::normalizeSubPath(subPath);
return DConfig::create(APP_ID, name, QStringLiteral("/") + normalized, parent);
}

ConfigLoader::ConfigLoader(QObject *parent)
: QObject(parent)
{
Expand Down Expand Up @@ -106,22 +111,36 @@
}
}

void ConfigLoader::updateValue(const QString &id, const QString &key, const QVariant &value)
bool ConfigLoader::updateValue(const QString &id, const QString &key, const QVariant &value)

Check warning on line 114 in src/plugin-qt/shortcut/src/config/configloader.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'updateValue' is never used.
{
if (!m_configs.contains(id)) {
qWarning() << "ConfigLoader: config not found or can not be changed:" << id << key << value;
return;
return false;
}

m_configs[id]->setValue(key, value);
return true;
}

bool ConfigLoader::canUpdateValue(const QString &id) const

Check warning on line 125 in src/plugin-qt/shortcut/src/config/configloader.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'canUpdateValue' is never used.
{
return m_configs.contains(id);
}

QSet<QString> ConfigLoader::discoverSubPaths()
{
// Accumulate all found subpaths
QSet<QString> foundSubPaths;
foundSubPaths.unite(scanIniSubPaths(CONFIG_SUBPATH_DIR));
foundSubPaths.unite(m_customStore.discoverSubPaths());

QDir regDir(CONFIG_SUBPATH_DIR);
return foundSubPaths;
}

QSet<QString> ConfigLoader::scanIniSubPaths(const QString &dirPath)
{
QSet<QString> foundSubPaths;

QDir regDir(dirPath);
if (!regDir.exists()) {
return foundSubPaths;
}
Expand All @@ -132,7 +151,7 @@
static const QRegularExpression reContinuation(QStringLiteral("\\\\\\s*\\n"));
QStringList iniFiles = regDir.entryList(QStringList() << "*.ini", QDir::Files | QDir::NoDotAndDotDot);
for (const QString &iniFile : iniFiles) {
QString fullPath = QDir(CONFIG_SUBPATH_DIR).absoluteFilePath(iniFile);
QString fullPath = regDir.absoluteFilePath(iniFile);
QFile file(fullPath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "ConfigLoader: Failed to open" << fullPath;
Expand Down Expand Up @@ -182,6 +201,122 @@
return foundSubPaths;
}

bool ConfigLoader::saveCustomShortcut(const KeyConfig &config)

Check warning on line 204 in src/plugin-qt/shortcut/src/config/configloader.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'saveCustomShortcut' is never used.
{
const QString subPath = CustomShortcutStore::normalizeSubPath(config.subPath);
DConfig *customDconfig = m_configs.value(subPath);
const bool existingDConfig = customDconfig;
if (!customDconfig) {
customDconfig = m_customStore.createConfig(subPath, this);
if (!customDconfig)
return false;
if (!customDconfig->isValid()) {
qWarning() << "ConfigLoader: failed to create custom shortcut DConfig:" << subPath;
delete customDconfig;
return false;
}
}

KeyConfig storedConfig = config;
storedConfig.subPath = subPath;
if (!m_customStore.save(storedConfig, customDconfig)) {
if (!existingDConfig) {
m_customStore.reset(customDconfig, subPath);
customDconfig->deleteLater();
}
return false;
}

auto existing = std::find_if(m_keys.begin(), m_keys.end(),
[&](const KeyConfig &item) { return item.subPath == subPath; });
if (existing != m_keys.end())
*existing = storedConfig;
else
m_keys.append(storedConfig);

m_loadedSubPaths.insert(subPath);
if (!m_configs.contains(subPath)) {
connect(customDconfig, &DConfig::valueChanged, this, [this, subPath, customDconfig](const QString &key) {
if (!customDconfig->isValid() || !m_configs.contains(subPath)) {
qWarning() << "DConfig invalid or not found:" << subPath;
return;
}

KeyConfig updatedConfig = parseKeyConfig(customDconfig);
qDebug() << "DConfig value changed:" << subPath << key;
auto existing = std::find_if(m_keys.begin(), m_keys.end(),
[&](const KeyConfig &item) { return item.subPath == subPath; });
if (existing != m_keys.end()) {
*existing = updatedConfig;
} else {
m_keys.append(updatedConfig);
}
emit keyConfigChanged(updatedConfig);
});
m_configs.insert(subPath, customDconfig);
}

return true;
}

bool ConfigLoader::updateCustomShortcut(const KeyConfig &config)

Check warning on line 262 in src/plugin-qt/shortcut/src/config/configloader.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'updateCustomShortcut' is never used.
{
const QString subPath = CustomShortcutStore::normalizeSubPath(config.subPath);
DConfig *customDconfig = m_configs.value(subPath);
if (!customDconfig) {
qWarning() << "ConfigLoader: custom shortcut config not found for update:" << subPath;
return false;
}

KeyConfig storedConfig = config;
storedConfig.subPath = subPath;
if (!m_customStore.updateCustomShortcutFields(storedConfig, customDconfig))
return false;

auto existing = std::find_if(m_keys.begin(), m_keys.end(),
[&](const KeyConfig &item) { return item.subPath == subPath; });
if (existing != m_keys.end())
*existing = storedConfig;
else
m_keys.append(storedConfig);

m_loadedSubPaths.insert(subPath);
return true;
}

bool ConfigLoader::removeCustomShortcut(const QString &subPath)

Check warning on line 287 in src/plugin-qt/shortcut/src/config/configloader.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'removeCustomShortcut' is never used.
{
const QString normalized = CustomShortcutStore::normalizeSubPath(subPath);
if (normalized.isEmpty()) {
return false;
}

DConfig *config = m_configs.take(normalized);
if (!config || !config->isValid()) {
qWarning() << "ConfigLoader: custom shortcut config not found for removal:" << subPath;
if (config) config->deleteLater();
return false;
} else {
disconnect(config, nullptr, this, nullptr);
}

m_customStore.reset(config, normalized);
if (!m_customStore.removeSubPath(normalized)) {
qWarning() << "ConfigLoader: failed to remove custom shortcut subPath after reset,"
<< "leaving a stale ini entry:" << normalized;
}

m_loadedSubPaths.remove(normalized);
m_keys.erase(std::remove_if(m_keys.begin(), m_keys.end(),
[&](const KeyConfig &config) { return config.subPath == normalized; }),
m_keys.end());

if (config)
config->deleteLater();

return true;
}

void ConfigLoader::loadConfig(const QString &subPath, bool newOne)
{
qDebug() << "Loading config from:" << subPath;
Expand All @@ -199,9 +334,8 @@
return;
}

DConfig *config = DConfig::create(APP_ID,
isKey ? CONFIG_NAME_SHORTCUT : CONFIG_NAME_GESTURE,
"/" + subPath, this);
DConfig *config = createDConfig(isKey ? CONFIG_NAME_SHORTCUT : CONFIG_NAME_GESTURE,
subPath, this);
if (!config->isValid()) {
qWarning() << "Failed to create DConfig for" << subPath;
delete config;
Expand Down Expand Up @@ -272,20 +406,22 @@
qDebug() << "DConfig value changed:" << subPath << key;
if (isKey) {
KeyConfig updatedConfig = parseKeyConfig(config);
for (auto &existing : m_keys) {
if (existing.subPath == subPath) {
existing = updatedConfig;
break;
}
auto existing = std::find_if(m_keys.begin(), m_keys.end(),
[&](const KeyConfig &item) { return item.subPath == subPath; });
if (existing != m_keys.end()) {
*existing = updatedConfig;
} else {
m_keys.append(updatedConfig);
}
emit keyConfigChanged(updatedConfig);
} else {
GestureConfig updatedConfig = parseGestureConfig(config);
for (auto &existing : m_gestures) {
if (existing.subPath == subPath) {
existing = updatedConfig;
break;
}
auto existing = std::find_if(m_gestures.begin(), m_gestures.end(),
[&](const GestureConfig &item) { return item.subPath == subPath; });
if (existing != m_gestures.end()) {
*existing = updatedConfig;
} else {
m_gestures.append(updatedConfig);
}
emit gestureConfigChanged(updatedConfig);
}
Expand All @@ -295,15 +431,10 @@
}
}

static QString normalizedSubpath(const QString &raw)
{
return raw.startsWith(QLatin1Char('/')) ? raw.mid(1) : raw;
}

KeyConfig ConfigLoader::parseKeyConfig(DConfig *config)
{
KeyConfig keyConfig;
keyConfig.subPath = normalizedSubpath(config->subpath());
keyConfig.subPath = CustomShortcutStore::normalizeSubPath(config->subpath());
keyConfig.appId = config->value("appId").toString();
keyConfig.displayName = config->value("displayName").toString();
keyConfig.enabled = config->value("enabled").toBool();
Expand All @@ -324,7 +455,7 @@
GestureConfig ConfigLoader::parseGestureConfig(DConfig *config)
{
GestureConfig gestureConfig;
gestureConfig.subPath = normalizedSubpath(config->subpath());
gestureConfig.subPath = CustomShortcutStore::normalizeSubPath(config->subpath());
gestureConfig.appId = config->value("appId").toString();
gestureConfig.displayName = config->value("displayName").toString();
gestureConfig.enabled = config->value("enabled").toBool();
Expand Down
Loading
Loading