#include "LOGIC/Lgc_Func_Button_Private.h" #include #include namespace { bool Lgc_FunctionButton_IsSequenceSeparator(QChar Character) { return Character.isSpace() || (Character == QLatin1Char(',')) || (Character == QLatin1Char(';')) || (Character == QLatin1Char('|')) || (Character == QChar(0xFF0C)) || (Character == QChar(0xFF1B)) || (Character == QChar(0x3001)); } quint16 Lgc_FunctionButton_GetUsageFromDigit(QChar Character) { switch (Character.unicode()) { case '0': return 0x0062; case '1': return 0x0059; case '2': return 0x005A; case '3': return 0x005B; case '4': return 0x005C; case '5': return 0x005D; case '6': return 0x005E; case '7': return 0x005F; case '8': return 0x0060; case '9': return 0x0061; default: return 0; } } quint16 Lgc_FunctionButton_GetUsageFromSymbol(QChar Character) { switch (Character.unicode()) { case '+': return 0x0057; case '/': return 0x0054; case '*': return 0x0055; case '-': return 0x0056; case '.': return 0x0063; default: return 0; } } } // namespace bool Lgc_FunctionButton_ParseLegacySequenceText( const QString& Text, quint16 SourceUsage, QVector* p_UsageList, QString* p_ErrorText) { p_UsageList->clear(); if (p_ErrorText != nullptr) p_ErrorText->clear(); const QString UpperText = Text.toUpper(); int Index = 0; const QVector> TokenList = { { QStringLiteral("NUMLOCK"), 0x0053 }, { QStringLiteral("ENTER"), 0x0058 }, { QStringLiteral("DIVIDE"), 0x0054 }, { QStringLiteral("SLASH"), 0x0054 }, { QStringLiteral("MULTIPLY"), 0x0055 }, { QStringLiteral("ASTERISK"), 0x0055 }, { QStringLiteral("DECIMAL"), 0x0063 }, { QStringLiteral("MINUS"), 0x0056 }, { QStringLiteral("SOURCE"), SourceUsage }, { QStringLiteral("PLUS"), 0x0057 }, { QStringLiteral("STAR"), 0x0055 }, { QStringLiteral("SELF"), SourceUsage }, { QStringLiteral("DOT"), 0x0063 }, { QStringLiteral("NUM"), 0x0053 } }; while (Index < Text.size()) { const QChar Character = Text.at(Index); if (Lgc_FunctionButton_IsSequenceSeparator(Character)) { ++Index; continue; } if ((Index + 1) < Text.size()) { const QString Token = Text.mid(Index, 2); if ((Token == QStringLiteral("本键")) || (Token == QStringLiteral("自身"))) { p_UsageList->append(SourceUsage); Index += 2; continue; } } const quint16 DigitUsage = Lgc_FunctionButton_GetUsageFromDigit(Character); if (DigitUsage != 0) { p_UsageList->append(DigitUsage); ++Index; continue; } const quint16 SymbolUsage = Lgc_FunctionButton_GetUsageFromSymbol(Character); if (SymbolUsage != 0) { p_UsageList->append(SymbolUsage); ++Index; continue; } bool IsMatched = false; for (const auto& Token : TokenList) { if (!UpperText.mid(Index, Token.first.size()).compare(Token.first, Qt::CaseInsensitive)) { p_UsageList->append(Token.second); Index += Token.first.size(); IsMatched = true; break; } } if (IsMatched) { continue; } if (p_ErrorText != nullptr) { *p_ErrorText = QStringLiteral("无法识别的按键序列片段:%1").arg(Text.mid(Index, 8)); } p_UsageList->clear(); return false; } return true; } bool Lgc_FunctionButton_TryParseSequenceToken( const QString& Token, quint16 SourceUsage, Lgc_FunctionButton_Struct_SequenceKey* p_KeyItem) { const QString TrimmedToken = Token.trimmed(); const QString UpperToken = TrimmedToken.toUpper(); if (UpperToken.isEmpty()) { return false; } const auto SetKey = [p_KeyItem](WORD VirtualKey, DWORD ExtraFlags, bool IsModifier, const QString& Text) { p_KeyItem->Key = { VirtualKey, ExtraFlags, IsModifier }; p_KeyItem->Text = Text; }; if ((UpperToken == QStringLiteral("SOURCE")) || (UpperToken == QStringLiteral("SELF")) || (TrimmedToken == QStringLiteral("本键")) || (TrimmedToken == QStringLiteral("自身"))) { const auto SourceKey = Lgc_FunctionButton_GetWindowsKey(SourceUsage); if (SourceKey.VirtualKey == 0) { return false; } p_KeyItem->Key = SourceKey; p_KeyItem->Text = Lgc_FunctionButton_GetUsageShortText(SourceUsage); return true; } if ((UpperToken.size() == 1) && UpperToken.at(0).isLetterOrNumber()) { SetKey(static_cast(UpperToken.at(0).unicode()), 0, false, UpperToken); return true; } if (UpperToken == QStringLiteral("CTRL") || UpperToken == QStringLiteral("CONTROL")) { SetKey(VK_CONTROL, 0, true, QStringLiteral("Ctrl")); return true; } if (UpperToken == QStringLiteral("SHIFT")) { SetKey(VK_SHIFT, 0, true, QStringLiteral("Shift")); return true; } if (UpperToken == QStringLiteral("ALT")) { SetKey(VK_MENU, 0, true, QStringLiteral("Alt")); return true; } if (UpperToken == QStringLiteral("WIN") || UpperToken == QStringLiteral("META")) { SetKey(VK_LWIN, 0, true, QStringLiteral("Win")); return true; } if (UpperToken == QStringLiteral("ENTER")) { SetKey(VK_RETURN, 0, false, QStringLiteral("Enter")); return true; } if (UpperToken == QStringLiteral("NUMENTER")) { SetKey(VK_RETURN, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("NumEnter")); return true; } if (UpperToken == QStringLiteral("SPACE")) { SetKey(VK_SPACE, 0, false, QStringLiteral("Space")); return true; } if (UpperToken == QStringLiteral("TAB")) { SetKey(VK_TAB, 0, false, QStringLiteral("Tab")); return true; } if (UpperToken == QStringLiteral("ESC") || UpperToken == QStringLiteral("ESCAPE")) { SetKey(VK_ESCAPE, 0, false, QStringLiteral("Esc")); return true; } if (UpperToken == QStringLiteral("BACKSPACE")) { SetKey(VK_BACK, 0, false, QStringLiteral("Backspace")); return true; } if (UpperToken == QStringLiteral("DELETE")) { SetKey(VK_DELETE, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Delete")); return true; } if (UpperToken == QStringLiteral("INSERT")) { SetKey(VK_INSERT, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Insert")); return true; } if (UpperToken == QStringLiteral("HOME")) { SetKey(VK_HOME, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Home")); return true; } if (UpperToken == QStringLiteral("END")) { SetKey(VK_END, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("End")); return true; } if (UpperToken == QStringLiteral("PAGEUP")) { SetKey(VK_PRIOR, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("PageUp")); return true; } if (UpperToken == QStringLiteral("PAGEDOWN")) { SetKey(VK_NEXT, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("PageDown")); return true; } if (UpperToken == QStringLiteral("LEFT")) { SetKey(VK_LEFT, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Left")); return true; } if (UpperToken == QStringLiteral("RIGHT")) { SetKey(VK_RIGHT, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Right")); return true; } if (UpperToken == QStringLiteral("UP")) { SetKey(VK_UP, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Up")); return true; } if (UpperToken == QStringLiteral("DOWN")) { SetKey(VK_DOWN, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Down")); return true; } if (UpperToken == QStringLiteral("CAPSLOCK")) { SetKey(VK_CAPITAL, 0, false, QStringLiteral("CapsLock")); return true; } if (UpperToken == QStringLiteral("PRINTSCREEN")) { SetKey(VK_SNAPSHOT, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("PrintScreen")); return true; } if (UpperToken == QStringLiteral("SCROLLLOCK")) { SetKey(VK_SCROLL, 0, false, QStringLiteral("ScrollLock")); return true; } if (UpperToken == QStringLiteral("PAUSE")) { SetKey(VK_PAUSE, 0, false, QStringLiteral("Pause")); return true; } if (UpperToken == QStringLiteral("NUM0")) { SetKey(VK_NUMPAD0, 0, false, QStringLiteral("Num0")); return true; } if (UpperToken == QStringLiteral("NUM1")) { SetKey(VK_NUMPAD1, 0, false, QStringLiteral("Num1")); return true; } if (UpperToken == QStringLiteral("NUM2")) { SetKey(VK_NUMPAD2, 0, false, QStringLiteral("Num2")); return true; } if (UpperToken == QStringLiteral("NUM3")) { SetKey(VK_NUMPAD3, 0, false, QStringLiteral("Num3")); return true; } if (UpperToken == QStringLiteral("NUM4")) { SetKey(VK_NUMPAD4, 0, false, QStringLiteral("Num4")); return true; } if (UpperToken == QStringLiteral("NUM5")) { SetKey(VK_NUMPAD5, 0, false, QStringLiteral("Num5")); return true; } if (UpperToken == QStringLiteral("NUM6")) { SetKey(VK_NUMPAD6, 0, false, QStringLiteral("Num6")); return true; } if (UpperToken == QStringLiteral("NUM7")) { SetKey(VK_NUMPAD7, 0, false, QStringLiteral("Num7")); return true; } if (UpperToken == QStringLiteral("NUM8")) { SetKey(VK_NUMPAD8, 0, false, QStringLiteral("Num8")); return true; } if (UpperToken == QStringLiteral("NUM9")) { SetKey(VK_NUMPAD9, 0, false, QStringLiteral("Num9")); return true; } if (UpperToken == QStringLiteral("NUM/")) { SetKey(VK_DIVIDE, KEYEVENTF_EXTENDEDKEY, false, QStringLiteral("Num/")); return true; } if (UpperToken == QStringLiteral("NUM*")) { SetKey(VK_MULTIPLY, 0, false, QStringLiteral("Num*")); return true; } if (UpperToken == QStringLiteral("NUM-")) { SetKey(VK_SUBTRACT, 0, false, QStringLiteral("Num-")); return true; } if (UpperToken == QStringLiteral("NUM+")) { SetKey(VK_ADD, 0, false, QStringLiteral("Num+")); return true; } if (UpperToken == QStringLiteral("NUM.")) { SetKey(VK_DECIMAL, 0, false, QStringLiteral("Num.")); return true; } if (UpperToken == QStringLiteral("COMMA")) { SetKey(VK_OEM_COMMA, 0, false, QStringLiteral("Comma")); return true; } if (UpperToken == QStringLiteral("PERIOD")) { SetKey(VK_OEM_PERIOD, 0, false, QStringLiteral("Period")); return true; } if (UpperToken == QStringLiteral("SEMICOLON")) { SetKey(VK_OEM_1, 0, false, QStringLiteral("Semicolon")); return true; } if (UpperToken == QStringLiteral("SLASH")) { SetKey(VK_OEM_2, 0, false, QStringLiteral("Slash")); return true; } if (UpperToken == QStringLiteral("GRAVE")) { SetKey(VK_OEM_3, 0, false, QStringLiteral("Grave")); return true; } if (UpperToken == QStringLiteral("LEFTBRACKET")) { SetKey(VK_OEM_4, 0, false, QStringLiteral("LeftBracket")); return true; } if (UpperToken == QStringLiteral("BACKSLASH")) { SetKey(VK_OEM_5, 0, false, QStringLiteral("Backslash")); return true; } if (UpperToken == QStringLiteral("RIGHTBRACKET")) { SetKey(VK_OEM_6, 0, false, QStringLiteral("RightBracket")); return true; } if (UpperToken == QStringLiteral("QUOTE")) { SetKey(VK_OEM_7, 0, false, QStringLiteral("Quote")); return true; } if (UpperToken == QStringLiteral("MINUS")) { SetKey(VK_OEM_MINUS, 0, false, QStringLiteral("Minus")); return true; } if (UpperToken == QStringLiteral("EQUAL")) { SetKey(VK_OEM_PLUS, 0, false, QStringLiteral("Equal")); return true; } const QRegularExpression FunctionKeyPattern(QStringLiteral("^F(\\d{1,2})$")); const QRegularExpressionMatch Match = FunctionKeyPattern.match(UpperToken); if (Match.hasMatch()) { const int FunctionIndex = Match.captured(1).toInt(); if ((FunctionIndex >= 1) && (FunctionIndex <= 24)) { SetKey( static_cast(VK_F1 + FunctionIndex - 1), 0, false, QStringLiteral("F%1").arg(FunctionIndex)); return true; } } return false; } bool Lgc_FunctionButton_ParseRecordedSequenceText( const QString& Text, quint16 SourceUsage, QVector* p_KeyList, QString* p_ErrorText) { p_KeyList->clear(); if (p_ErrorText != nullptr) p_ErrorText->clear(); const QStringList TokenList = Text.split( QRegularExpression(QStringLiteral("[\\s,;|,;、]+")), QString::SkipEmptyParts); if (TokenList.isEmpty()) { return false; } for (const QString& Token : TokenList) { Lgc_FunctionButton_Struct_SequenceKey KeyItem; if (!Lgc_FunctionButton_TryParseSequenceToken(Token, SourceUsage, &KeyItem)) { if (p_ErrorText != nullptr) { *p_ErrorText = QStringLiteral("无法识别的按键序列片段:%1").arg(Token); } p_KeyList->clear(); return false; } p_KeyList->append(KeyItem); } return true; } bool Lgc_FunctionButton_IsSameWindowsKey( const Lgc_FunctionButton_Struct_WindowsKey& Left, const Lgc_FunctionButton_Struct_WindowsKey& Right) { return (Left.VirtualKey == Right.VirtualKey) && (Left.ExtraFlags == Right.ExtraFlags); } bool Lgc_FunctionButton_ParseKeyCombinationText( const QString& Text, quint16 SourceUsage, QVector* p_KeyList, QString* p_ErrorText) { p_KeyList->clear(); if (p_ErrorText != nullptr) p_ErrorText->clear(); QStringList TokenList; if (Text.contains(QLatin1Char('+'))) { TokenList = Text.split( QRegularExpression(QStringLiteral("\\s*\\+\\s*")), QString::SkipEmptyParts); } else { TokenList = Text.split( QRegularExpression(QStringLiteral("[\\s,;|,;、]+")), QString::SkipEmptyParts); } for (const QString& Token : TokenList) { Lgc_FunctionButton_Struct_SequenceKey KeyItem; if (!Lgc_FunctionButton_TryParseSequenceToken(Token, SourceUsage, &KeyItem)) { if (p_ErrorText != nullptr) { *p_ErrorText = QStringLiteral("无法识别的按键片段:%1").arg(Token); } p_KeyList->clear(); return false; } p_KeyList->append(KeyItem); } return !p_KeyList->isEmpty(); } QString Lgc_FunctionButton_FormatKeyCombination( const QVector& KeyList) { QStringList TextList; for (const auto& KeyItem : KeyList) { TextList.append(KeyItem.Text); } return TextList.join(QStringLiteral("+")); } QVector> Lgc_FunctionButton_GroupSequenceKeysIntoCombinations( const QVector& KeyList) { QVector> CombinationList; QVector ModifierList; for (const auto& KeyItem : KeyList) { if (KeyItem.Key.IsModifier) { bool IsDuplicate = false; for (const auto& OldModifier : ModifierList) { if (Lgc_FunctionButton_IsSameWindowsKey(OldModifier.Key, KeyItem.Key)) { IsDuplicate = true; break; } } if (!IsDuplicate) { ModifierList.append(KeyItem); } continue; } QVector Combination = ModifierList; Combination.append(KeyItem); CombinationList.append(Combination); } if (CombinationList.isEmpty() && !ModifierList.isEmpty()) { CombinationList.append(ModifierList); } return CombinationList; } bool Lgc_FunctionButton_ParseShortcutSequenceText( const QString& Text, quint16 SourceUsage, QVector>* p_CombinationList, QString* p_ErrorText) { p_CombinationList->clear(); if (p_ErrorText != nullptr) p_ErrorText->clear(); const QStringList SegmentList = Text.split( QRegularExpression(QStringLiteral("\\s*(?:->|=>|→)\\s*")), QString::SkipEmptyParts); if (SegmentList.size() > 1) { for (const QString& SegmentText : SegmentList) { QVector Combination; if (!Lgc_FunctionButton_ParseKeyCombinationText( SegmentText, SourceUsage, &Combination, p_ErrorText)) { p_CombinationList->clear(); return false; } p_CombinationList->append(Combination); } return !p_CombinationList->isEmpty(); } QVector FlatKeyList; if (!Lgc_FunctionButton_ParseRecordedSequenceText( Text, SourceUsage, &FlatKeyList, p_ErrorText)) { QVector SingleCombination; if (!Lgc_FunctionButton_ParseKeyCombinationText( Text, SourceUsage, &SingleCombination, p_ErrorText)) { return false; } p_CombinationList->append(SingleCombination); return true; } *p_CombinationList = Lgc_FunctionButton_GroupSequenceKeysIntoCombinations(FlatKeyList); return !p_CombinationList->isEmpty(); } QString Lgc_FunctionButton_FormatShortcutSequence( const QVector>& CombinationList) { QStringList TextList; for (const auto& Combination : CombinationList) { TextList.append(Lgc_FunctionButton_FormatKeyCombination(Combination)); } return TextList.join(QStringLiteral(" -> ")); } QVector Lgc_FunctionButton_ConvertUsageListToSequenceKeys( const QVector& UsageList) { QVector KeyList; for (quint16 Usage : UsageList) { const auto Key = Lgc_FunctionButton_GetWindowsKey(Usage); if (Key.VirtualKey == 0) { KeyList.clear(); return KeyList; } Lgc_FunctionButton_Struct_SequenceKey KeyItem; KeyItem.Key = Key; KeyItem.Text = Lgc_FunctionButton_GetUsageShortText(Usage); KeyList.append(KeyItem); } return KeyList; }