diff --git a/src/blackmisc/hwkeyboardkey.cpp b/src/blackmisc/hwkeyboardkey.cpp new file mode 100644 index 000000000..cf891b72c --- /dev/null +++ b/src/blackmisc/hwkeyboardkey.cpp @@ -0,0 +1,327 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "hwkeyboardkey.h" +#include "blackmiscfreefunctions.h" +#include + +namespace BlackMisc +{ + namespace Hardware + { + CKeyboardKey::CKeyboardKey() : + m_key(0), m_modifier1(ModifierNone), m_modifier2(ModifierNone), m_function(HotkeyNone), m_pressed(false) + {} + + CKeyboardKey::CKeyboardKey(int keyCode, Modifier modifier1, Modifier modifier2, const HotkeyFunction &function, bool isPressed) : + m_key(keyCode), m_modifier1(modifier1), m_modifier2(modifier2), m_function(function), m_pressed(isPressed) + {} + + uint CKeyboardKey::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_key); + hashs << qHash(this->m_function); + hashs << qHash(static_cast(this->m_modifier1)); + hashs << qHash(static_cast(this->m_modifier2)); + return BlackMisc::calculateHash(hashs, "CKeyboardKey"); + } + + void CKeyboardKey::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + QString CKeyboardKey::convertToQString(bool /* i18n */) const + { + QString s = this->getModifier1AsString(); + s.append(" ").append(this->getModifier2AsString()).append(" "); + if (this->m_key != 0) this->getKeyAsStringRepresentation(); + return s.trimmed(); + } + + int CKeyboardKey::getMetaTypeId() const + { + return qMetaTypeId(); + } + + bool CKeyboardKey::isA(int metaTypeId) const + { + return (metaTypeId == qMetaTypeId()); + } + + int CKeyboardKey::compareImpl(const CValueObject &otherBase) const + { + const auto &other = static_cast(otherBase); + QString k1(this->m_key); + QString k2(other.getKey()); + return k1.compare(k2); + } + + void CKeyboardKey::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_key; + argument << static_cast(this->m_modifier1); + argument << static_cast(this->m_modifier2); + argument << static_cast(this->m_function); + argument << this->m_pressed; + } + + void CKeyboardKey::unmarshallFromDbus(const QDBusArgument &argument) + { + uint c; + argument >> this->m_key; + argument >> c; + this->m_modifier1 = static_cast(c); + argument >> c; + this->m_modifier2 = static_cast(c); + argument >> c; + this->m_function = static_cast(c); + argument >> this->m_pressed; + } + + QString CKeyboardKey::modifierToString(CKeyboardKey::Modifier modifier) + { + switch (modifier) + { + case ModifierNone: return ""; + case ModifierAltAny: return "Alt"; + case ModifierAltLeft: return "Alt Left"; + case ModifierAltRight: return "Alt Right"; + case ModifierShiftAny: return "Shift"; + case ModifierShiftLeft: return "Shift Left"; + case ModifierShiftRight: return "Shift Right"; + case ModifierCtrlAny: return "Ctrl"; + case ModifierCtrlLeft: return "Ctrl Left"; + case ModifierCtrlRight: return "Ctrl Right"; + case ModifierMeta: return "Meta"; + default: + qFatal("Wrong modifier"); + return ""; + } + } + + CKeyboardKey::Modifier CKeyboardKey::modifierFromString(const QString &modifier) + { + QString mod = modifier.toLower().replace('&', ' '); + if (mod == "ctrl" || mod == "ctl") return ModifierCtrlAny; + if (mod.startsWith("ctrl l") || mod.startsWith("ctl l")) return ModifierCtrlLeft; + if (mod.startsWith("ctrl r") || mod.startsWith("ctl r")) return ModifierCtrlRight; + + if (mod == "shift") return ModifierShiftAny; + if (mod.startsWith("shift l")) return ModifierShiftLeft; + if (mod.startsWith("shift r")) return ModifierShiftRight; + + if (mod == "alt") return ModifierAltAny; + if (mod.startsWith("alt l")) return ModifierAltLeft; + if (mod.startsWith("alt r")) return ModifierAltRight; + + if (mod == "meta") return ModifierMeta; + + return ModifierNone; + } + + CKeyboardKey::Modifier CKeyboardKey::modifierFromQtModifier(Qt::Modifier qtModifier) + { + switch (qtModifier) + { + case Qt::META : return ModifierMeta; + case Qt::SHIFT : return ModifierShiftAny; + case Qt::CTRL: return ModifierShiftAny; + case Qt::ALT: return ModifierAltAny; + default: + return ModifierNone; + } + } + + const QStringList &CKeyboardKey::modifiers() + { + static QStringList modifiers; + if (modifiers.isEmpty()) + { + modifiers << modifierToString(ModifierNone); + modifiers << modifierToString(ModifierCtrlAny); + modifiers << modifierToString(ModifierCtrlLeft); + modifiers << modifierToString(ModifierCtrlRight); + modifiers << modifierToString(ModifierShiftAny); + modifiers << modifierToString(ModifierShiftLeft); + modifiers << modifierToString(ModifierShiftRight); + modifiers << modifierToString(ModifierAltAny); + modifiers << modifierToString(ModifierAltLeft); + modifiers << modifierToString(ModifierAltRight); + modifiers << modifierToString(ModifierMeta); + } + return modifiers; + } + + bool CKeyboardKey::operator ==(const CKeyboardKey &other) const + { + return (other.getKey() != this->getKey()) && + other.isPressed() == this->isPressed() && + other.getFunction() == this->getFunction() && + other.getModifier1() == this->getModifier1() && + other.getModifier2() == this->getModifier2(); + } + + bool CKeyboardKey::operator< (CKeyboardKey const &other) const + { + if (this->getKey() < other.getKey()) + return true; + else + return false; + } + + void CKeyboardKey::cleanup() + { + if (!this->hasModifier()) return; + if (this->m_modifier1 == ModifierNone) qSwap(this->m_modifier1, this->m_modifier2); + if (this->numberOfModifiers() == 1) return; + if (this->m_modifier1 == this->m_modifier2) + { + // redundant + this->m_modifier2 = ModifierNone; + return; + } + + // order + if (static_cast(this->m_modifier1) < static_cast(this->m_modifier2)) + qSwap(this->m_modifier1, this->m_modifier2); + } + + int CKeyboardKey::numberOfModifiers() const + { + if (!this->hasModifier()) return 0; + if (this->m_modifier1 == ModifierNone || this->m_modifier2 == ModifierNone) return 1; + return 2; + } + + void CKeyboardKey::setKey(const QString &key) + { + if (key.isEmpty()) + this->m_key = 0; + else if (key.contains(QRegExp("\\((\\d+)\\)"))) + { + QString code = key.mid(key.indexOf("(") + 1).replace(")", ""); + if (code.isEmpty()) + this->m_key = 0; + else + this->m_key = code.toInt(); + } + else + this->setKey(key.at(0)); + } + + void CKeyboardKey::setKey(const QChar key) + { + if (key.isNull()) + this->m_key = 0; + else + this->m_key = key.digitValue(); + } + + QString CKeyboardKey::getFunctionAsString() const + { + switch (this->m_function) + { + case HotkeyNone: return ""; + case HotkeyPtt: return QCoreApplication::translate("Hotkey", "PTT"); + case HotkeyOpacity50: return QCoreApplication::translate("Hotkey", "Opacity 50%"); + case HotkeyOpacity100: return QCoreApplication::translate("Hotkey", "Opacity 100%"); + case HotkeyToggleCom1: return QCoreApplication::translate("Hotkey", "Toggle COM1"); + case HotkeyToggleCom2: return QCoreApplication::translate("Hotkey", "Toggle COM2"); + default: + qFatal("Wrong function"); + return ""; + } + + // force strings for translation in resource files + (void)QT_TRANSLATE_NOOP("Hotkey", "PTT"); + (void)QT_TRANSLATE_NOOP("Hotkey", "Opacity 50%"); + (void)QT_TRANSLATE_NOOP("Hotkey", "Opacity 100%"); + (void)QT_TRANSLATE_NOOP("Hotkey", "Toggle COM1"); + (void)QT_TRANSLATE_NOOP("Hotkey", "Toggle COM2"); + } + + QVariant CKeyboardKey::propertyByIndex(int index) const + { + switch (index) + { + case IndexFunction: + return QVariant(this->m_function); + case IndexFunctionAsString: + return QVariant(this->getFunctionAsString()); + case IndexModifier1: + return QVariant(static_cast(this->m_modifier1)); + case IndexModifier2: + return QVariant(static_cast(this->m_modifier2)); + case IndexModifier1AsString: + return QVariant(this->getModifier1AsString()); + case IndexModifier2AsString: + return QVariant(this->getModifier2AsString()); + case IndexKey: + return QVariant(this->m_key); + case IndexKeyAsString: + return QVariant(QString(QChar(this->m_key))); + case IndexKeyAsStringRepresentation: + return QVariant(this->getKeyAsStringRepresentation()); + case IndexIsPressed: + return QVariant(this->m_pressed); + default: + break; + } + + Q_ASSERT_X(false, "CKeyboardKey", "index unknown"); + QString m = QString("no property, index ").append(QString::number(index)); + return QVariant::fromValue(m); + } + + QString CKeyboardKey::toStringRepresentation(int key) + { + if (key == 0) return ""; + QString ks = QKeySequence(key).toString(); + ks.append('(').append(QString::number(key)).append(')'); + return ks; + } + + void CKeyboardKey::setPropertyByIndex(const QVariant &variant, int index) + { + switch (index) + { + case IndexFunction: + { + uint f = variant.value(); + this->setFunction(static_cast(f)); + break; + } + case IndexKey: + case IndexKeyAsString: + case IndexKeyAsStringRepresentation: + { + // static_cast see docu of variant.type() + if (static_cast(variant.type()) == QMetaType::QChar) + this->setKey(variant.value()); + else + this->setKey(variant.value()); + break; + } + case IndexIsPressed: + this->setPressed(variant.value()); + break; + case IndexModifier1AsString: + this->setModifier1(variant.value()); + break; + case IndexModifier2AsString: + this->setModifier2(variant.value()); + break; + default: + Q_ASSERT_X(false, "CKeyboardKey", "index unknown (setter)"); + break; + } + } + } // namespace Hardware + + +} // BlackMisc diff --git a/src/blackmisc/hwkeyboardkey.h b/src/blackmisc/hwkeyboardkey.h new file mode 100644 index 000000000..d63b28b51 --- /dev/null +++ b/src/blackmisc/hwkeyboardkey.h @@ -0,0 +1,230 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/*! + \file +*/ + +#ifndef BLACKMISC_KEYBOARDKEY_H +#define BLACKMISC_KEYBOARDKEY_H + +#include "valueobject.h" +#include +#include + +namespace BlackMisc +{ + namespace Hardware + { + /*! + * \brief Value object representing a keyboard key. + */ + class CKeyboardKey : public CValueObject + { + public: + + //! \brief Properties by index + enum ColumnIndex + { + IndexKey = 0, + IndexKeyAsString, + IndexKeyAsStringRepresentation, + IndexModifier1, + IndexModifier2, + IndexModifier1AsString, + IndexModifier2AsString, + IndexFunction, + IndexFunctionAsString, + IndexIsPressed + }; + + //! \brief Function + enum HotkeyFunction + { + HotkeyNone, + HotkeyPtt, + HotkeyToggleCom1, + HotkeyToggleCom2, + HotkeyOpacity50, + HotkeyOpacity100 + }; + + //! \brief Modifier + enum Modifier + { + ModifierNone, + ModifierCtrlLeft, + ModifierCtrlRight, + ModifierCtrlAny, + ModifierAltLeft, + ModifierAltRight, + ModifierAltAny, + ModifierShiftLeft, + ModifierShiftRight, + ModifierShiftAny, + ModifierMeta, + ModifierNum + }; + + //! \brief Default constructor + CKeyboardKey(); + + //! \brief Constructor + CKeyboardKey(int keyCode, Modifier modifier1 = ModifierNone, Modifier modifier2 = ModifierNone, const HotkeyFunction &function = HotkeyNone, bool isPressed = false); + + //! \brief Destructor + ~CKeyboardKey() {} + + //! \copydoc CValueObject::toQVariant + virtual QVariant toQVariant() const override + { + return QVariant::fromValue(*this); + } + + //! \copydoc CValueObject::getValueHash + virtual uint getValueHash() const override; + + //! \brief Register metadata + static void registerMetadata(); + + //! \brief Equal? + bool operator ==(const CKeyboardKey &other) const; + + //! \brief < + bool operator<(CKeyboardKey const &other) const; + + //! \brief key pressed? + bool isPressed() const { return this->m_pressed; } + + //! \brief Set key pressed + void setPressed(bool isPressed) { this->m_pressed = isPressed; } + + //! \brief Get key code + QChar getKey() const { return QChar(this->m_key); } + + //! \brief Get key code + QString getKeyAsString() const { return QString(this->getKey()); } + + //! \brief Get key code + QString getKeyAsStringRepresentation() const { return CKeyboardKey::toStringRepresentation(this->m_key); } + + //! \brief As Qt::Key + Qt::Key getKeyAsQtKey() const { return static_cast(this->m_key);} + + //! \brief Set key code + void setKey(const QString &key); + + //! \brief Set key code + void setKey(const QChar key); + + //! \brief number of modifiers + int numberOfModifiers() const; + + //! \brief Function (optional) + HotkeyFunction getFunction() const { return this->m_function; } + + //! \brief Modifier 1 + Modifier getModifier1() const { return this->m_modifier1; } + + //! \brief Modifier 2 + Modifier getModifier2() const { return this->m_modifier2; } + + //! \brief Modifier 1 + QString getModifier1AsString() const { return modifierToString(this->m_modifier1); } + + //! \brief Modifier 2 + QString getModifier2AsString() const { return modifierToString(this->m_modifier2); } + + //! \brief Set modifier 1 + void setModifier1(const QString &modifier) { this->m_modifier1 = modifierFromString(modifier); } + + //! \brief Set modifier 2 + void setModifier2(const QString &modifier) { this->m_modifier2 = modifierFromString(modifier); } + + //! \brief Modifier? + bool hasModifier() const + { + return this->m_modifier1 != ModifierNone || this->m_modifier2 != ModifierNone; + } + + //! \brief with key? + bool hasKey() const + { + return !this->m_key == 0; + } + + //! \brief Key + modifier? + bool hasKeyAndModifier() const + { + return this->hasKey() && this->hasModifier(); + } + + //! Order Modifiers + void cleanup(); + + //! \brief Function (optional) + QString getFunctionAsString() const; + + //! \brief Set function + void setFunction(const HotkeyFunction &function) { this->m_function = function; } + + //! \copydoc CValueObject::setPropertyByIndex + virtual void setPropertyByIndex(const QVariant &variant, int index); + + //! \copydoc CValueObject::propertyByIndex + virtual QVariant propertyByIndex(int index) const; + + //! \brief Modifier to string + static QString modifierToString(Modifier modifier); + + //! \brief Modifier from string + static Modifier modifierFromString(const QString &modifier); + + //! \brief Modifier from Qt::Modifier + static Modifier modifierFromQtModifier(Qt::Modifier qtModifier); + + //! \brief all modifiers + static const QStringList &modifiers(); + + /*! + * \brief CKeyboardKey::toStringRepresentation + * \param key + * \return + */ + static QString toStringRepresentation(int key); + + protected: + //! \copydoc CValueObject::convertToQString + virtual QString convertToQString(bool i18n = false) const override; + + //! \copydoc CValueObject::getMetaTypeId + virtual int getMetaTypeId() const override; + + //! \copydoc CValueObject::isA + virtual bool isA(int metaTypeId) const override; + + //! \copydoc CValueObject::compareImpl(otherBase) + virtual int compareImpl(const CValueObject &otherBase) const override; + + //! \copydoc CValueObject::marshallToDbus + virtual void marshallToDbus(QDBusArgument &argument) const override; + + //! \copydoc CValueObject::unmarshallFromDbus + virtual void unmarshallFromDbus(const QDBusArgument &argument) override; + + private: + int m_key; + Modifier m_modifier1; + Modifier m_modifier2; + HotkeyFunction m_function; + bool m_pressed; + + }; + } // class +} // BlackMisc + +Q_DECLARE_METATYPE(BlackMisc::Hardware::CKeyboardKey) + +#endif // guard