File indexing completed on 2024-05-12 17:07:15

0001 /*
0002     SPDX-FileCopyrightText: 2010 Andriy Rysin <rysin@kde.org>
0003     SPDX-FileCopyrightText: 2021 Cyril Rossi <cyril.rossi@enioka.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "keyboard_config.h"
0009 #include "debug.h"
0010 
0011 #include <KConfigGroup>
0012 #include <KSharedConfig>
0013 
0014 static const QStringList SWITCHING_POLICIES = {QStringLiteral("Global"), QStringLiteral("Desktop"), QStringLiteral("WinClass"), QStringLiteral("Window")};
0015 const int KeyboardConfig::NO_LOOPING = -1;
0016 
0017 static KeyboardConfig::SwitchingPolicy findStringIndex(const QString &toFind, KeyboardConfig::SwitchingPolicy defaultPolicy)
0018 {
0019     const int index = SWITCHING_POLICIES.indexOf(toFind);
0020     if (index < 0) {
0021         return defaultPolicy;
0022     }
0023     return static_cast<KeyboardConfig::SwitchingPolicy>(index);
0024 }
0025 
0026 KeyboardConfig::KeyboardConfig(QObject *parent)
0027     : KeyboardSettingsBase(parent)
0028     , m_referenceLayoutLoopCount(mLayoutLoopCount)
0029 {
0030     layouts.clear();
0031 }
0032 
0033 KeyboardConfig::SwitchingPolicy KeyboardConfig::switchingPolicy() const
0034 {
0035     return findStringIndex(switchMode(), SWITCH_POLICY_GLOBAL);
0036 }
0037 
0038 void KeyboardConfig::setSwitchingPolicy(KeyboardConfig::SwitchingPolicy switchingPolicy)
0039 {
0040     setSwitchMode(SWITCHING_POLICIES.at(switchingPolicy));
0041 }
0042 
0043 KeyboardConfig::SwitchingPolicy KeyboardConfig::defaultSwitchingPolicyValue() const
0044 {
0045     return findStringIndex(defaultSwitchModeValue(), SWITCH_POLICY_GLOBAL);
0046 }
0047 
0048 bool KeyboardConfig::layoutsSaveNeeded() const
0049 {
0050     if (layouts.size() != m_referenceLayouts.size()) {
0051         return true;
0052     }
0053     if (mLayoutLoopCount != m_referenceLayoutLoopCount) {
0054         return true;
0055     }
0056 
0057     // Due to layoutUnit operator==() that does not test all properties.
0058     // Do not compare shortcuts, they are automatically applied
0059     bool isSaveNeeded = false;
0060     for (int i = 0; i < layouts.size(); ++i) {
0061         isSaveNeeded |= layouts.at(i).getDisplayName() != m_referenceLayouts.at(i).getDisplayName();
0062         isSaveNeeded |= layouts.at(i).layout() != m_referenceLayouts.at(i).layout();
0063         isSaveNeeded |= layouts.at(i).variant() != m_referenceLayouts.at(i).variant();
0064         if (isSaveNeeded) {
0065             return isSaveNeeded;
0066         }
0067     }
0068     return isSaveNeeded;
0069 }
0070 
0071 QString KeyboardConfig::getSwitchingPolicyString(SwitchingPolicy switchingPolicy)
0072 {
0073     return SWITCHING_POLICIES.at(switchingPolicy);
0074 }
0075 
0076 void KeyboardConfig::setDefaults()
0077 {
0078     layouts.clear();
0079 }
0080 
0081 void KeyboardConfig::load()
0082 {
0083     KeyboardSettingsBase::load();
0084 
0085     const QStringList layoutStrings = layoutList();
0086     const QStringList variants = variantList();
0087     const QStringList names = displayNames();
0088 
0089     layouts.clear();
0090     for (int i = 0; i < layoutStrings.size(); ++i) {
0091         if (i < variants.size()) {
0092             layouts.append({layoutStrings[i], variants[i]});
0093         } else {
0094             layouts.append(LayoutUnit(layoutStrings[i]));
0095         }
0096 
0097         if (i < names.size() && !names[i].isEmpty() && names[i] != layouts[i].layout()) {
0098             layouts[i].setDisplayName(names[i]);
0099         }
0100     }
0101 
0102     // layouts' shortcuts are retrieved from GlobalShortcuts in KCMKeyboardWidget
0103     m_referenceLayouts = layouts;
0104     m_referenceLayoutLoopCount = mLayoutLoopCount;
0105 
0106     qCDebug(KCM_KEYBOARD) << "configuring layouts" << configureLayouts() << "configuring options" << resetOldXkbOptions();
0107 }
0108 
0109 void KeyboardConfig::save()
0110 {
0111     m_referenceLayouts = layouts;
0112     m_referenceLayoutLoopCount = mLayoutLoopCount;
0113 
0114     QStringList layoutList;
0115     QStringList variants;
0116     QStringList displayNames;
0117     for (const LayoutUnit &layoutUnit : qAsConst(layouts)) {
0118         layoutList.append(layoutUnit.layout());
0119         variants.append(layoutUnit.variant());
0120         displayNames.append(layoutUnit.getRawDisplayName());
0121     }
0122 
0123     // QStringLists with a single empty string are serialized as "\\0", avoid that
0124     // by saving them as an empty list instead. This way it can be passed as-is to
0125     // libxkbcommon/setxkbmap. Before KConfigXT it used QStringList::join(",").
0126     if (variants.size() == 1 && variants.constFirst().isEmpty()) {
0127         variants.clear();
0128     }
0129     if (displayNames.size() == 1 && displayNames.constFirst().isEmpty()) {
0130         displayNames.clear();
0131     }
0132 
0133     setLayoutList(layoutList);
0134     setVariantList(variants);
0135     setDisplayNames(displayNames);
0136 
0137     KeyboardSettingsBase::save();
0138 }
0139 
0140 QList<LayoutUnit> KeyboardConfig::getDefaultLayouts() const
0141 {
0142     QList<LayoutUnit> defaultLayoutList;
0143     int i = 0;
0144     for (const LayoutUnit &layoutUnit : qAsConst(layouts)) {
0145         defaultLayoutList.append(layoutUnit);
0146         if (layoutLoopCount() != KeyboardConfig::NO_LOOPING && i >= layoutLoopCount() - 1) {
0147             break;
0148         }
0149         i++;
0150     }
0151     return defaultLayoutList;
0152 }
0153 
0154 QList<LayoutUnit> KeyboardConfig::getExtraLayouts() const
0155 {
0156     if (layoutLoopCount() == KeyboardConfig::NO_LOOPING) {
0157         return QList<LayoutUnit>();
0158     }
0159 
0160     return layouts.mid(layoutLoopCount(), layouts.size());
0161 }