File indexing completed on 2024-05-12 17:07:19
0001 /* 0002 SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "standardshortcutsmodel.h" 0008 0009 #include <QCollator> 0010 #include <QMetaEnum> 0011 0012 #include <KConfigBase> 0013 #include <KConfigGroup> 0014 #include <KLocalizedString> 0015 #include <KStandardShortcut> 0016 0017 #include "basemodel.h" 0018 #include "kcmkeys_debug.h" 0019 0020 StandardShortcutsModel::StandardShortcutsModel(QObject *parent) 0021 : BaseModel(parent) 0022 { 0023 } 0024 0025 void StandardShortcutsModel::load() 0026 { 0027 beginResetModel(); 0028 m_components.clear(); 0029 m_components.resize(6); 0030 const ComponentType sectionName = ComponentType::CommonAction; 0031 auto index = [](KStandardShortcut::Category category) { 0032 return static_cast<int>(category); 0033 }; 0034 m_components[index(KStandardShortcut::Category::File)] = Component{"File", i18n("File"), sectionName, "document-multiple", {}, false, false}; 0035 m_components[index(KStandardShortcut::Category::Edit)] = Component{"Edit", i18n("Edit"), sectionName, "edittext", {}, false, false}; 0036 m_components[index(KStandardShortcut::Category::Navigation)] = 0037 Component{"Navigation", i18n("Navigation"), sectionName, "preferences-desktop-navigation", {}, false, false}; 0038 m_components[index(KStandardShortcut::Category::View)] = Component{"View", i18n("View"), sectionName, "view-preview", {}, false, false}; 0039 m_components[index(KStandardShortcut::Category::Settings)] = Component{"Settings", i18n("Settings"), sectionName, "settings-configure", {}, false, false}; 0040 m_components[index(KStandardShortcut::Category::Help)] = Component{"Help", i18n("Help"), sectionName, "system-help", {}, false, false}; 0041 for (int i = KStandardShortcut::AccelNone + 1; i < KStandardShortcut::StandardShortcutCount; ++i) { 0042 const auto id = static_cast<KStandardShortcut::StandardShortcut>(i); 0043 const QList<QKeySequence> activeShortcuts = KStandardShortcut::shortcut(id); 0044 const QList<QKeySequence> defaultShortcuts = KStandardShortcut::hardcodedDefaultShortcut(id); 0045 auto listToSet = [](const QList<QKeySequence> &list) { 0046 return QSet<QKeySequence>{list.cbegin(), list.cend()}; 0047 }; 0048 const Action a{KStandardShortcut::name(id), 0049 KStandardShortcut::label(id), 0050 listToSet(activeShortcuts), 0051 listToSet(defaultShortcuts), 0052 listToSet(activeShortcuts)}; 0053 m_components[static_cast<int>(category(id))].actions.append(a); 0054 } 0055 QCollator collator; 0056 collator.setCaseSensitivity(Qt::CaseInsensitive); 0057 collator.setNumericMode(true); 0058 std::for_each(m_components.begin(), m_components.end(), [&](Component &c) { 0059 std::sort(c.actions.begin(), c.actions.end(), [&](const Action &a1, const Action &a2) { 0060 return collator.compare(a1.displayName, a2.displayName) < 0; 0061 }); 0062 }); 0063 std::sort(m_components.begin(), m_components.end(), [&](Component &c1, Component &c2) { 0064 return collator.compare(c1.displayName, c2.displayName) < 0; 0065 }); 0066 endResetModel(); 0067 } 0068 0069 void StandardShortcutsModel::exportToConfig(const KConfigBase &config) 0070 { 0071 KConfigGroup group(&config, "StandardShortcuts"); 0072 for (const auto &component : qAsConst(m_components)) { 0073 if (component.checked) { 0074 for (const auto &action : component.actions) { 0075 const QList<QKeySequence> shortcutsList(action.activeShortcuts.cbegin(), action.activeShortcuts.cend()); 0076 group.writeEntry(action.id, QKeySequence::listToString(shortcutsList)); 0077 } 0078 } 0079 } 0080 } 0081 0082 void StandardShortcutsModel::importConfig(const KConfigBase &config) 0083 { 0084 if (!config.hasGroup("StandardShortcuts")) { 0085 qCDebug(KCMKEYS) << "Config has no StandardShortcuts group"; 0086 return; 0087 } 0088 const KConfigGroup group = config.group("StandardShortcuts"); 0089 const QStringList keys = group.keyList(); 0090 for (const auto &key : keys) { 0091 KStandardShortcut::StandardShortcut id = KStandardShortcut::findByName(key); 0092 if (id == KStandardShortcut::AccelNone) { 0093 qCWarning(KCMKEYS) << "Unknown standard shortcut" << key; 0094 continue; 0095 } 0096 QString name; 0097 switch (category(id)) { 0098 case KStandardShortcut::Category::File: 0099 name = "File"; 0100 break; 0101 case KStandardShortcut::Category::Edit: 0102 name = "Edit"; 0103 break; 0104 case KStandardShortcut::Category::Navigation: 0105 name = "Navigation"; 0106 break; 0107 case KStandardShortcut::Category::View: 0108 name = "View"; 0109 break; 0110 case KStandardShortcut::Category::Settings: 0111 name = "Settings"; 0112 break; 0113 case KStandardShortcut::Category::Help: 0114 name = "Help"; 0115 break; 0116 } 0117 auto cat = std::find_if(m_components.begin(), m_components.end(), [&name](const Component &c) { 0118 return c.id == name; 0119 }); 0120 if (cat == m_components.end()) { 0121 qCWarning(KCMKEYS) << "No category for standard shortcut" << key; 0122 continue; 0123 } 0124 auto action = std::find_if(cat->actions.begin(), cat->actions.end(), [&](const Action &a) { 0125 return a.id == key; 0126 }); 0127 if (action == cat->actions.end()) { 0128 qCWarning(KCMKEYS) << "Model doesn't include action" << key; 0129 continue; 0130 } 0131 const auto shortcuts = QKeySequence::listFromString(group.readEntry(key)); 0132 const QSet<QKeySequence> shortcutsSet(shortcuts.cbegin(), shortcuts.cend()); 0133 if (shortcutsSet != action->activeShortcuts) { 0134 action->activeShortcuts = shortcutsSet; 0135 const QModelIndex i = index(action - cat->actions.begin(), 0, index(cat - m_components.begin(), 0)); 0136 Q_EMIT dataChanged(i, i, {CustomShortcutsRole, ActiveShortcutsRole}); 0137 } 0138 } 0139 } 0140 0141 void StandardShortcutsModel::save() 0142 { 0143 for (auto &component : m_components) { 0144 for (auto &action : component.actions) { 0145 if (action.initialShortcuts != action.activeShortcuts) { 0146 QList<QKeySequence> keys(action.activeShortcuts.cbegin(), action.activeShortcuts.cend()); 0147 KStandardShortcut::saveShortcut(KStandardShortcut::findByName(action.id), keys); 0148 action.initialShortcuts = action.activeShortcuts; 0149 } 0150 } 0151 } 0152 }