Created
October 14, 2021 20:08
-
-
Save jsm222/6babf9c8660b628a47b5946a5e34627e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/override.cpp b/override.cpp | |
index a5a38e3..119a2a9 100644 | |
--- a/override.cpp | |
+++ b/override.cpp | |
@@ -11,57 +11,111 @@ | |
#include <cstdlib> | |
#define _GNU_SOURCE | |
-#include <dlfcn.h> | |
-// Override | |
-// QString toString(SequenceFormat format = PortableText) const; | |
-// which is defined in /usr/local/include/qt5/QtGui/qkeysequence.h | |
-// and is implemented in | |
-// https://github.com/qt/qtbase/blob/7dd81686e8e9ee86624c5bcca10688cfb360dcb8/src/gui/kernel/qkeysequence.cpp#L1666-L1678 | |
- | |
-// Found this by running | |
-// strings /usr/local/lib/qt5/* | grep KeySeq | grep tring | sort | uniq | |
-const char* FUNC_SYMBOL = "_ZNK12QKeySequence8toStringENS_14SequenceFormatE"; | |
+static inline void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format); | |
+class QKeySequencePrivate | |
+{ | |
+public: | |
+ enum { MaxKeyCount = 4 }; // also used in QKeySequenceEdit | |
+ inline QKeySequencePrivate() : ref(1) | |
+ { | |
+ std::fill_n(key, uint(MaxKeyCount), 0); | |
+ } | |
+ inline QKeySequencePrivate(const QKeySequencePrivate ©) : ref(1) | |
+ { | |
+ std::copy(copy.key, copy.key + MaxKeyCount, | |
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(key, MaxKeyCount)); | |
+ } | |
+ QAtomicInt ref; | |
+ int key[MaxKeyCount]; | |
+ static QString encodeString(int key, QKeySequence::SequenceFormat format); | |
+ // used in dbusmenu | |
+ Q_GUI_EXPORT static QString keyName(int key, QKeySequence::SequenceFormat format); | |
+ static int decodeString(QString accel, QKeySequence::SequenceFormat format); | |
+}; | |
+QKeySequencePrivate *d; | |
+QString QKeySequence::toString(SequenceFormat format) const | |
+{ | |
+ QString finalString; | |
+ // A standard string, with no translation or anything like that. In some ways it will | |
+ // look like our latin case on Windows and X11 | |
+ int end = count(); | |
+ for (int i = 0; i < end; ++i) { | |
+ finalString += d->encodeString(d->key[i], format); | |
+ finalString += QLatin1String(", "); | |
+ } | |
+ finalString.truncate(finalString.length() - 2); | |
+ return finalString; | |
+} | |
-static const int kShiftUnicode = 0x21E7; | |
-static const int kControlUnicode = 0x2303; | |
-static const int kOptionUnicode = 0x2325; | |
-static const int kCommandUnicode = 0x2318; | |
-typedef QString (*orig_func_f_type)(const QKeySequence *, QKeySequence::SequenceFormat format); | |
-QString QKeySequence::toString(SequenceFormat format) const | |
+QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat format) | |
{ | |
- | |
- // Use some nuts function pointer black magic to access the original function | |
- orig_func_f_type orig_func; | |
- orig_func = (orig_func_f_type)dlsym(RTLD_NEXT, FUNC_SYMBOL); | |
- QString result = orig_func(this, format); | |
- | |
- // Replacements based on table from | |
- // https://github.com/qt/qtbase/blob/7dd81686e8e9ee86624c5bcca10688cfb360dcb8/src/gui/kernel/qkeysequence.cpp#L73-L94 | |
- result.replace(QCoreApplication::translate("QShortcut", "Esc"), QChar(0x238B)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Tab"), QChar(0x21E5)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Backtab"), QChar(0x21E4)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Backspace"), QChar(0x232B)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Return"), QChar(0x21B5)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Enter"), QChar(0x2324)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Del"), QChar(0x2326)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Home"), QChar(0x2196)); | |
- result.replace(QCoreApplication::translate("QShortcut", "End"), QChar(0x2198)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Left"), QChar(0x2190)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Up"), QChar(0x2191)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Right"), QChar(0x2192)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Down"), QChar(0x2193)); | |
- result.replace(QCoreApplication::translate("QShortcut", "PgUp"), QChar(0x21DE)); | |
- result.replace(QCoreApplication::translate("QShortcut", "PgDown"), QChar(0x21DF)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Shift"), QChar(kShiftUnicode)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Ctrl"), QChar(kCommandUnicode)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Meta"), QChar(kControlUnicode)); | |
- result.replace(QCoreApplication::translate("QShortcut", "Alt"), QChar(kOptionUnicode)); | |
- result.replace(QCoreApplication::translate("QShortcut", "CapsLock"), QChar(0x21EA)); | |
- | |
- result.replace("+", ""); | |
- | |
- return(result); | |
+ bool nativeText = (format == QKeySequence::NativeText); | |
+ QString s; | |
+ // Handle -1 (Invalid Key) and Qt::Key_unknown gracefully | |
+ if (key == -1 || key == Qt::Key_unknown) | |
+ return s; | |
+#if defined(Q_OS_MACX) | |
+ if (nativeText) { | |
+ // On OS X the order (by default) is Meta, Alt, Shift, Control. | |
+ // If the AA_MacDontSwapCtrlAndMeta is enabled, then the order | |
+ // is Ctrl, Alt, Shift, Meta. The macSymbolForQtKey does this swap | |
+ // for us, which means that we have to adjust our order here. | |
+ // The upshot is a lot more infrastructure to keep the number of | |
+ // if tests down and the code relatively clean. | |
+ static const int ModifierOrder[] = { Qt::META, Qt::ALT, Qt::SHIFT, Qt::CTRL, 0 }; | |
+ static const int QtKeyOrder[] = { Qt::Key_Meta, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Control, 0 }; | |
+ static const int DontSwapModifierOrder[] = { Qt::CTRL, Qt::ALT, Qt::SHIFT, Qt::META, 0 }; | |
+ static const int DontSwapQtKeyOrder[] = { Qt::Key_Control, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Meta, 0 }; | |
+ const int *modifierOrder; | |
+ const int *qtkeyOrder; | |
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { | |
+ modifierOrder = DontSwapModifierOrder; | |
+ qtkeyOrder = DontSwapQtKeyOrder; | |
+ } else { | |
+ modifierOrder = ModifierOrder; | |
+ qtkeyOrder = QtKeyOrder; | |
+ } | |
+ for (int i = 0; modifierOrder[i] != 0; ++i) { | |
+ if (key & modifierOrder[i]) | |
+ s += qt_macSymbolForQtKey(qtkeyOrder[i]); | |
+ } | |
+ } else | |
+#endif | |
+ { | |
+ // On other systems the order is Meta, Control, Alt, Shift | |
+ if ((key & Qt::META) == Qt::META) | |
+ s = nativeText ? QCoreApplication::translate("QShortcut", "Meta") : QString::fromLatin1("Meta"); | |
+ if ((key & Qt::CTRL) == Qt::CTRL) | |
+ addKey(s, nativeText ? QStringLiteral("⌘") : QStringLiteral("⌘"), format); | |
+ if ((key & Qt::ALT) == Qt::ALT) | |
+ addKey(s, nativeText ? QCoreApplication::translate("QShortcut", "Alt") : QString::fromLatin1("Alt"), format); | |
+ if ((key & Qt::SHIFT) == Qt::SHIFT) | |
+ addKey(s, nativeText ? QCoreApplication::translate("QShortcut", "Shift") : QString::fromLatin1("Shift"), format); | |
+ } | |
+ if ((key & Qt::KeypadModifier) == Qt::KeypadModifier) | |
+ addKey(s, nativeText ? QCoreApplication::translate("QShortcut", "Num") : QString::fromLatin1("Num"), format); | |
+ QString p = keyName(key, format); | |
+#if defined(Q_OS_OSX) | |
+ if (nativeText) | |
+ s += p; | |
+ else | |
+#endif | |
+ addKey(s, p, format); | |
+ return s; | |
} | |
+static inline void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format) | |
+{ | |
+ if (!str.isEmpty()) { | |
+ if (format == QKeySequence::NativeText) { | |
+ //: Key separator in shortcut string | |
+ str += QCoreApplication::translate("QShortcut", "+"); | |
+ } else { | |
+ str += QLatin1Char('+'); | |
+ } | |
+ } | |
+ str += theKey; | |
+} | |
+ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment