File indexing completed on 2024-05-12 04:06:25
0001 /* 0002 SPDX-FileCopyrightText: 2010 Stefan Majewsky <majewsky@gmx.net> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "trigger.h" 0008 0009 #include <QMap> 0010 #include <KLocalizedString> 0011 0012 namespace 0013 { 0014 class ByteArrayList : public QList<QByteArray> 0015 { 0016 public: 0017 QByteArray join(const QChar& separator) const 0018 { 0019 char sep = separator.toLatin1(); 0020 if (isEmpty()) 0021 return QByteArray(); 0022 int size = -1; 0023 for (int i = 0; i < count(); ++i) 0024 size += 1 + at(i).size(); 0025 QByteArray result; 0026 result.reserve(size); 0027 for (int i = 0; i < count(); ++i) 0028 { 0029 if (i != 0) 0030 result.append(sep); 0031 result.append(at(i)); 0032 } 0033 return result; 0034 } 0035 }; 0036 0037 template<typename T, typename ListType> struct TriggerData 0038 { 0039 QMap<Qt::KeyboardModifier, T> m_modifierStrings; 0040 QMap<Qt::MouseButton, T> m_buttonStrings; 0041 QMap<Qt::Orientation, T> m_orientationStrings; 0042 0043 T modifierString(Qt::KeyboardModifiers modifiers, const QChar& separator) const 0044 { 0045 typename QMap<Qt::KeyboardModifier, T>::const_iterator it1 = m_modifierStrings.begin(), it2 = m_modifierStrings.end(); 0046 ListType modifierStrings; 0047 for (; it1 != it2; ++it1) 0048 if (modifiers & it1.key()) 0049 modifierStrings << it1.value(); 0050 return modifierStrings.join(separator); 0051 } 0052 0053 T actionString(Qt::Orientation wheelDirection, Qt::MouseButton button) const 0054 { 0055 if (m_orientationStrings.contains(wheelDirection)) 0056 return m_orientationStrings.value(wheelDirection); 0057 else 0058 return m_buttonStrings.value(button); 0059 } 0060 }; 0061 0062 struct TriggerParserData : public TriggerData<QByteArray, ByteArrayList> 0063 { 0064 TriggerParserData() 0065 { 0066 m_modifierStrings[Qt::ShiftModifier] = "ShiftModifier"; 0067 m_modifierStrings[Qt::ControlModifier] = "ControlModifier"; 0068 m_modifierStrings[Qt::AltModifier] = "AltModifier"; 0069 m_modifierStrings[Qt::MetaModifier] = "MetaModifier"; 0070 m_modifierStrings[Qt::GroupSwitchModifier] = "GroupSwitchModifier"; 0071 m_buttonStrings[Qt::NoButton] = "NoButton"; 0072 m_buttonStrings[Qt::LeftButton] = "LeftButton"; 0073 m_buttonStrings[Qt::RightButton] = "RightButton"; 0074 m_buttonStrings[Qt::MiddleButton] = "MidButton"; 0075 m_buttonStrings[Qt::XButton1] = "XButton1"; 0076 m_buttonStrings[Qt::XButton2] = "XButton2"; 0077 m_orientationStrings[Qt::Horizontal] = "wheel:Horizontal"; 0078 m_orientationStrings[Qt::Vertical] = "wheel:Vertical"; 0079 } 0080 }; 0081 0082 struct TriggerPrinterData : public TriggerData<QString, QStringList> 0083 { 0084 TriggerPrinterData() 0085 { 0086 //FIXME: These are probably wrong for Macs. 0087 m_modifierStrings[Qt::ShiftModifier] = i18nc("a keyboard modifier", "Shift"); 0088 m_modifierStrings[Qt::ControlModifier] = i18nc("a keyboard modifier", "Ctrl"); 0089 m_modifierStrings[Qt::AltModifier] = i18nc("a keyboard modifier", "Alt"); 0090 m_modifierStrings[Qt::MetaModifier] = i18nc("a keyboard modifier", "Meta"); 0091 m_modifierStrings[Qt::GroupSwitchModifier] = i18nc("a special keyboard modifier", "GroupSwitch"); 0092 m_buttonStrings[Qt::NoButton] = i18nc("refers to no mouse buttons being pressed", "No-Button"); 0093 //FIXME: Left/right may be wrong if mouse buttons are swapped. 0094 m_buttonStrings[(Qt::MouseButton) -1] = QStringLiteral("%1"); //allow external users to insert their custom strings into here 0095 m_buttonStrings[Qt::LeftButton] = i18nc("a mouse button", "Left-Button"); 0096 m_buttonStrings[Qt::RightButton] = i18nc("a mouse button", "Right-Button"); 0097 m_buttonStrings[Qt::MiddleButton] = i18nc("a mouse button", "Middle-Button"); 0098 m_buttonStrings[Qt::XButton1] = i18nc("a special mouse button", "XButton1"); 0099 m_buttonStrings[Qt::XButton2] = i18nc("a special mouse button", "XButton2"); 0100 m_orientationStrings[Qt::Horizontal] = i18n("Horizontal-Scroll"); 0101 m_orientationStrings[Qt::Vertical] = i18n("Vertical-Scroll"); 0102 } 0103 }; 0104 } 0105 0106 Q_GLOBAL_STATIC(TriggerParserData, tParserData) 0107 Q_GLOBAL_STATIC(TriggerPrinterData, tPrinterData) 0108 0109 Palapeli::Trigger::Trigger() 0110 : m_modifiers(Qt::NoModifier) 0111 , m_button((Qt::MouseButton) -1) 0112 , m_wheelDirection((Qt::Orientation) 0) 0113 { 0114 } 0115 0116 Palapeli::Trigger::Trigger(const QByteArray& serialization) 0117 : m_modifiers(Qt::NoModifier) 0118 , m_button((Qt::MouseButton) -1) 0119 , m_wheelDirection((Qt::Orientation) 0) 0120 { 0121 //expect format "BUTTON_OR_WHEEL;MODIFIERLIST", i.e. two sections separated by semicolon 0122 const QList<QByteArray> sections = serialization.split(';'); 0123 if (sections.size() != 2) 0124 return; 0125 //parse modifier list (separated by vertical pipes) -> We do this first because this one can fail. 0126 Qt::KeyboardModifiers modifiers = Qt::NoModifier; 0127 if (sections[1] != "NoModifier") 0128 { 0129 const QList<QByteArray> modifierStrings = sections[1].split('|'); 0130 for (const QByteArray& modifierString : modifierStrings) 0131 { 0132 Qt::KeyboardModifier modifier = tParserData->m_modifierStrings.key(modifierString, Qt::NoModifier); 0133 if (modifier == Qt::NoModifier) 0134 return; //parsing failed 0135 modifiers |= modifier; 0136 } 0137 } 0138 m_modifiers = modifiers; 0139 //parse first section (button or wheel direction) -> default to NoButton + NoOrientation if parsing fails 0140 m_button = tParserData->m_buttonStrings.key(sections[0], Qt::NoButton); 0141 m_wheelDirection = tParserData->m_orientationStrings.key(sections[0], (Qt::Orientation) 0); 0142 } 0143 0144 bool Palapeli::Trigger::isValid() const 0145 { 0146 if (m_wheelDirection > 0 && m_button > 0) 0147 return false; //do not allow wheel and mouse triggers at the same time 0148 else 0149 return m_button != ((Qt::MouseButton) -1); //do not allow 'negative' m_button values 0150 } 0151 0152 QByteArray Palapeli::Trigger::serialized() const 0153 { 0154 if (!isValid()) 0155 return QByteArray(); 0156 const QByteArray actionString = tParserData->actionString(m_wheelDirection, m_button); 0157 QByteArray modifierString = tParserData->modifierString(m_modifiers, QLatin1Char('|')); 0158 if (modifierString.isEmpty()) 0159 modifierString = "NoModifier"; 0160 return actionString + QByteArray(1, ';') + modifierString; 0161 } 0162 0163 QString Palapeli::Trigger::toString() const 0164 { 0165 const QString actionString = tPrinterData->actionString(m_wheelDirection, m_button); 0166 const QString modifierString = tPrinterData->modifierString(m_modifiers, QLatin1Char('+')); 0167 if (modifierString.isEmpty()) 0168 return actionString; 0169 else 0170 return modifierString + QLatin1Char('+') + actionString; 0171 } 0172 0173 Qt::KeyboardModifiers Palapeli::Trigger::modifiers() const 0174 { 0175 return m_modifiers; 0176 } 0177 0178 void Palapeli::Trigger::setModifiers(Qt::KeyboardModifiers modifiers) 0179 { 0180 m_modifiers = modifiers; 0181 } 0182 0183 Qt::MouseButton Palapeli::Trigger::button() const 0184 { 0185 return m_button; 0186 } 0187 0188 void Palapeli::Trigger::setButton(Qt::MouseButton button) 0189 { 0190 m_button = button; 0191 if (m_button != Qt::NoButton) 0192 m_wheelDirection = (Qt::Orientation) 0; 0193 } 0194 0195 Qt::Orientation Palapeli::Trigger::wheelDirection() const 0196 { 0197 return m_wheelDirection; 0198 } 0199 0200 void Palapeli::Trigger::setWheelDirection(Qt::Orientation orientation) 0201 { 0202 m_wheelDirection = orientation; 0203 if (m_wheelDirection != (Qt::Orientation) 0) 0204 m_button = Qt::NoButton; 0205 } 0206 0207 bool Palapeli::Trigger::operator==(const Palapeli::Trigger& other) const 0208 { 0209 return m_modifiers == other.m_modifiers 0210 && m_button == other.m_button 0211 && m_wheelDirection == other.m_wheelDirection; 0212 }