|
30 | 30 | #include "fcitx-utils/i18n.h" |
31 | 31 | #include "fcitx-utils/log.h" |
32 | 32 | #include "fcitx-utils/misc.h" |
| 33 | +#include "fcitx-utils/key.h" |
33 | 34 | #include "fcitx-utils/stringutils.h" |
34 | 35 | #include "fcitx-utils/unixfd.h" |
35 | 36 | #include "fcitx/addonfactory.h" |
@@ -730,6 +731,130 @@ class Controller1 : public ObjectVTable<Controller1> { |
730 | 731 | {}}; |
731 | 732 | } |
732 | 733 |
|
| 734 | + std::vector<dbus::DBusStruct<std::string, std::string, std::string, |
| 735 | + std::string, std::vector<std::string>>> |
| 736 | + getAllHotkeys() { |
| 737 | + std::vector<dbus::DBusStruct<std::string, std::string, std::string, |
| 738 | + std::string, std::vector<std::string>>> |
| 739 | + result; |
| 740 | + |
| 741 | + auto addHotkeyList = |
| 742 | + [&result](const std::string &category, const std::string &name, |
| 743 | + const std::string &uniqueName, |
| 744 | + const std::string &description, const KeyList &keys) { |
| 745 | + std::vector<std::string> keyStrings; |
| 746 | + for (const auto &key : keys) { |
| 747 | + keyStrings.push_back(key.toString()); |
| 748 | + } |
| 749 | + result.emplace_back(category, name, uniqueName, description, |
| 750 | + keyStrings); |
| 751 | + }; |
| 752 | + |
| 753 | + auto processKeyOption = |
| 754 | + [&addHotkeyList]( |
| 755 | + const std::string &optionType, const std::string &category, |
| 756 | + const std::string &name, const std::string &uniqueName, |
| 757 | + const std::string &optionDesc, |
| 758 | + const std::shared_ptr<RawConfig> &valueConfig) { |
| 759 | + if (optionType.find("List|Key") == std::string::npos && |
| 760 | + optionType.find("Key") == std::string::npos) { |
| 761 | + return; |
| 762 | + } |
| 763 | + |
| 764 | + if (valueConfig == nullptr) { |
| 765 | + return; |
| 766 | + } |
| 767 | + |
| 768 | + std::string keyString; |
| 769 | + if (optionType.find("List|Key") != std::string::npos) { |
| 770 | + valueConfig->visitSubItems( |
| 771 | + [&keyString](const RawConfig &item, |
| 772 | + const std::string & /*path*/) { |
| 773 | + if (!keyString.empty()) { |
| 774 | + keyString += " "; |
| 775 | + } |
| 776 | + keyString += item.value(); |
| 777 | + return true; |
| 778 | + }); |
| 779 | + } else { |
| 780 | + keyString = valueConfig->value(); |
| 781 | + } |
| 782 | + |
| 783 | + try { |
| 784 | + KeyList keys = Key::keyListFromString(keyString); |
| 785 | + addHotkeyList(category, name, uniqueName, optionDesc, keys); |
| 786 | + } catch (...) { |
| 787 | + FCITX_WARN() |
| 788 | + << "Failed to parse KeyList from: " << keyString; |
| 789 | + } |
| 790 | + }; |
| 791 | + |
| 792 | + // get global config |
| 793 | + RawConfig globalRawConfig; |
| 794 | + instance_->globalConfig().save(globalRawConfig); |
| 795 | + auto globalConfigDesc = |
| 796 | + dumpDBusConfigDescription(instance_->globalConfig().config()); |
| 797 | + |
| 798 | + // process the global config shortcuts |
| 799 | + for (const auto &typeInfo : globalConfigDesc) { |
| 800 | + const auto &options = std::get<1>(typeInfo); |
| 801 | + for (const auto &optionInfo : options) { |
| 802 | + const auto &optionName = std::get<0>(optionInfo); |
| 803 | + const auto &optionType = std::get<1>(optionInfo); |
| 804 | + const auto &optionDesc = std::get<2>(optionInfo); |
| 805 | + |
| 806 | + // the global config shortcuts stored at 'Hotkey/optionName' |
| 807 | + std::string configPath = "Hotkey/" + optionName; |
| 808 | + auto valueConfig = globalRawConfig.get(configPath); |
| 809 | + std::string category = "Global"; |
| 810 | + processKeyOption(optionType, category, "", optionName, |
| 811 | + optionDesc, valueConfig); |
| 812 | + } |
| 813 | + } |
| 814 | + |
| 815 | + // get current group inputmethods config |
| 816 | + const auto &inputMethodManager = instance_->inputMethodManager(); |
| 817 | + const auto &groupName = inputMethodManager.currentGroup().name(); |
| 818 | + const auto *group = inputMethodManager.group(groupName); |
| 819 | + if (group == nullptr) { |
| 820 | + return result; |
| 821 | + } |
| 822 | + |
| 823 | + for (const auto &item : group->inputMethodList()) { |
| 824 | + const auto *entry = inputMethodManager.entry(item.name()); |
| 825 | + if (entry == nullptr || !entry->isConfigurable()) { |
| 826 | + continue; |
| 827 | + } |
| 828 | + |
| 829 | + const auto *engine = instance_->inputMethodEngine(item.name()); |
| 830 | + const auto *config = |
| 831 | + engine ? engine->getConfigForInputMethod(*entry) : nullptr; |
| 832 | + if (config == nullptr) { |
| 833 | + continue; |
| 834 | + } |
| 835 | + |
| 836 | + auto imConfigDesc = dumpDBusConfigDescription(*config); |
| 837 | + RawConfig rawConfig; |
| 838 | + config->save(rawConfig); |
| 839 | + |
| 840 | + // process the inputmethod config shortcuts |
| 841 | + for (const auto &typeInfo : imConfigDesc) { |
| 842 | + const auto &options = std::get<1>(typeInfo); |
| 843 | + for (const auto &optionInfo : options) { |
| 844 | + const auto &optionName = std::get<0>(optionInfo); |
| 845 | + const auto &optionType = std::get<1>(optionInfo); |
| 846 | + const auto &optionDesc = std::get<2>(optionInfo); |
| 847 | + auto valueConfig = rawConfig.get(optionName); |
| 848 | + std::string category = "InputMethod"; |
| 849 | + processKeyOption(optionType, category, entry->uniqueName(), |
| 850 | + optionName, optionDesc, valueConfig); |
| 851 | + } |
| 852 | + } |
| 853 | + } |
| 854 | + |
| 855 | + return result; |
| 856 | + } |
| 857 | + |
733 | 858 | private: |
734 | 859 | DBusModule *module_; |
735 | 860 | Instance *instance_; |
@@ -801,6 +926,7 @@ class Controller1 : public ObjectVTable<Controller1> { |
801 | 926 | FCITX_OBJECT_VTABLE_METHOD(canRestart, "CanRestart", "", "b"); |
802 | 927 | FCITX_OBJECT_VTABLE_METHOD(currentInputMethodInfo, "CurrentInputMethodInfo", |
803 | 928 | "", "sssssssbsa{sv}"); |
| 929 | + FCITX_OBJECT_VTABLE_METHOD(getAllHotkeys, "GetAllHotkeys", "", "a(ssssas)"); |
804 | 930 | }; |
805 | 931 |
|
806 | 932 | DBusModule::DBusModule(Instance *instance) |
|
0 commit comments