├── .clang-format ├── .formatignore ├── .github └── workflows │ └── check.yml ├── .gitignore ├── CMakeLists.txt ├── COPYING ├── COPYING.unicode ├── LICENSES ├── GPL-2.0-or-later.txt └── LGPL-2.1-or-later.txt ├── Messages.sh ├── README.md ├── cmake ├── FindOpenCC.cmake └── FindPthread.cmake ├── config.h.in ├── gui ├── CMakeLists.txt ├── customphraseeditor │ ├── CMakeLists.txt │ ├── customphraseeditor.cpp │ ├── customphraseeditor.h │ ├── customphraseeditor.json │ ├── customphraseeditor.ui │ ├── customphrasemodel.cpp │ ├── customphrasemodel.h │ ├── editordialog.cpp │ ├── editordialog.h │ ├── editordialog.ui │ ├── main.cpp │ └── main.h └── pinyindictmanager │ ├── CMakeLists.txt │ ├── browserdialog.cpp │ ├── browserdialog.h │ ├── browserdialog.ui │ ├── filedownloader.cpp │ ├── filedownloader.h │ ├── filelistmodel.cpp │ ├── filelistmodel.h │ ├── guicommon.h │ ├── log.cpp │ ├── log.h │ ├── main.cpp │ ├── main.h │ ├── pinyindictmanager.cpp │ ├── pinyindictmanager.h │ ├── pinyindictmanager.json │ ├── pinyindictmanager.ui │ ├── pipeline.cpp │ ├── pipeline.h │ ├── pipelinejob.cpp │ ├── pipelinejob.h │ ├── processrunner.cpp │ ├── processrunner.h │ ├── renamefile.cpp │ └── renamefile.h ├── icon ├── 16x16 │ └── apps │ │ ├── fcitx-cangjie.png │ │ ├── fcitx-chn.png │ │ ├── fcitx-chttrans-active.png │ │ ├── fcitx-chttrans-inactive.png │ │ ├── fcitx-erbi.png │ │ ├── fcitx-fullwidth-active.png │ │ ├── fcitx-fullwidth-inactive.png │ │ ├── fcitx-pinyin.png │ │ ├── fcitx-punc-active.png │ │ ├── fcitx-punc-inactive.png │ │ ├── fcitx-remind-active.png │ │ ├── fcitx-remind-inactive.png │ │ ├── fcitx-shuangpin.png │ │ ├── fcitx-wbpy.png │ │ ├── fcitx-wubi.png │ │ ├── fcitx-ziranma.png │ │ ├── org.fcitx.Fcitx5.fcitx-cangjie.png │ │ ├── org.fcitx.Fcitx5.fcitx-chn.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-erbi.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-pinyin.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-shuangpin.png │ │ ├── org.fcitx.Fcitx5.fcitx-wbpy.png │ │ ├── org.fcitx.Fcitx5.fcitx-wubi.png │ │ └── org.fcitx.Fcitx5.fcitx-ziranma.png ├── 22x22 │ └── apps │ │ ├── fcitx-cangjie.png │ │ ├── fcitx-chn.png │ │ ├── fcitx-chttrans-active.png │ │ ├── fcitx-chttrans-inactive.png │ │ ├── fcitx-erbi.png │ │ ├── fcitx-fullwidth-active.png │ │ ├── fcitx-fullwidth-inactive.png │ │ ├── fcitx-pinyin.png │ │ ├── fcitx-punc-active.png │ │ ├── fcitx-punc-inactive.png │ │ ├── fcitx-remind-active.png │ │ ├── fcitx-remind-inactive.png │ │ ├── fcitx-shuangpin.png │ │ ├── fcitx-wbpy.png │ │ ├── fcitx-wubi.png │ │ ├── fcitx-ziranma.png │ │ ├── org.fcitx.Fcitx5.fcitx-cangjie.png │ │ ├── org.fcitx.Fcitx5.fcitx-chn.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-erbi.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-pinyin.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-shuangpin.png │ │ ├── org.fcitx.Fcitx5.fcitx-wbpy.png │ │ ├── org.fcitx.Fcitx5.fcitx-wubi.png │ │ └── org.fcitx.Fcitx5.fcitx-ziranma.png ├── 24x24 │ └── apps │ │ ├── fcitx-cangjie.png │ │ ├── fcitx-chn.png │ │ ├── fcitx-chttrans-active.png │ │ ├── fcitx-chttrans-inactive.png │ │ ├── fcitx-erbi.png │ │ ├── fcitx-fullwidth-active.png │ │ ├── fcitx-fullwidth-inactive.png │ │ ├── fcitx-pinyin.png │ │ ├── fcitx-punc-active.png │ │ ├── fcitx-punc-inactive.png │ │ ├── fcitx-remind-active.png │ │ ├── fcitx-remind-inactive.png │ │ ├── fcitx-shuangpin.png │ │ ├── fcitx-wbpy.png │ │ ├── fcitx-wubi.png │ │ ├── fcitx-ziranma.png │ │ ├── org.fcitx.Fcitx5.fcitx-cangjie.png │ │ ├── org.fcitx.Fcitx5.fcitx-chn.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-erbi.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-pinyin.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-shuangpin.png │ │ ├── org.fcitx.Fcitx5.fcitx-wbpy.png │ │ ├── org.fcitx.Fcitx5.fcitx-wubi.png │ │ └── org.fcitx.Fcitx5.fcitx-ziranma.png ├── 48x48 │ └── apps │ │ ├── fcitx-cangjie.png │ │ ├── fcitx-chn.png │ │ ├── fcitx-chttrans-active.png │ │ ├── fcitx-chttrans-inactive.png │ │ ├── fcitx-erbi.png │ │ ├── fcitx-fullwidth-active.png │ │ ├── fcitx-fullwidth-inactive.png │ │ ├── fcitx-pinyin.png │ │ ├── fcitx-punc-active.png │ │ ├── fcitx-punc-inactive.png │ │ ├── fcitx-remind-active.png │ │ ├── fcitx-remind-inactive.png │ │ ├── fcitx-shuangpin.png │ │ ├── fcitx-wbpy.png │ │ ├── fcitx-wubi.png │ │ ├── fcitx-ziranma.png │ │ ├── org.fcitx.Fcitx5.fcitx-cangjie.png │ │ ├── org.fcitx.Fcitx5.fcitx-chn.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-chttrans-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-erbi.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-pinyin.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-punc-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-active.png │ │ ├── org.fcitx.Fcitx5.fcitx-remind-inactive.png │ │ ├── org.fcitx.Fcitx5.fcitx-shuangpin.png │ │ ├── org.fcitx.Fcitx5.fcitx-wbpy.png │ │ ├── org.fcitx.Fcitx5.fcitx-wubi.png │ │ └── org.fcitx.Fcitx5.fcitx-ziranma.png ├── CMakeLists.txt └── scalable │ └── apps │ ├── fcitx-fullwidth-active-symbolic.svg │ ├── fcitx-fullwidth-active.svg │ ├── fcitx-fullwidth-inactive-symbolic.svg │ ├── fcitx-fullwidth-inactive.svg │ ├── fcitx-punc-active-symbolic.svg │ ├── fcitx-punc-active.svg │ ├── fcitx-punc-inactive-symbolic.svg │ ├── fcitx-punc-inactive.svg │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-active-symbolic.svg │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-active.svg │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-inactive-symbolic.svg │ ├── org.fcitx.Fcitx5.fcitx-fullwidth-inactive.svg │ ├── org.fcitx.Fcitx5.fcitx-punc-active-symbolic.svg │ ├── org.fcitx.Fcitx5.fcitx-punc-active.svg │ ├── org.fcitx.Fcitx5.fcitx-punc-inactive-symbolic.svg │ └── org.fcitx.Fcitx5.fcitx-punc-inactive.svg ├── im ├── CMakeLists.txt ├── pinyin │ ├── CMakeLists.txt │ ├── chaizi.txt │ ├── customphrase.cpp │ ├── customphrase.h │ ├── pinyin-addon.conf.in.in │ ├── pinyin.conf.in │ ├── pinyin.cpp │ ├── pinyin.h │ ├── pinyin.lua │ ├── pinyincandidate.cpp │ ├── pinyincandidate.h │ ├── pinyinenginefactory.cpp │ ├── pinyinenginefactory.h │ ├── shuangpin.conf.in │ ├── symboldictionary.cpp │ ├── symboldictionary.h │ ├── symbols │ ├── workerthread.cpp │ └── workerthread.h └── table │ ├── CMakeLists.txt │ ├── candidate.cpp │ ├── candidate.h │ ├── cangjie.conf.in.in │ ├── context.cpp │ ├── context.h │ ├── db.conf.in.in │ ├── engine.cpp │ ├── engine.h │ ├── erbi.conf.in.in │ ├── factory.cpp │ ├── factory.h │ ├── ime.cpp │ ├── ime.h │ ├── qxm.conf.in.in │ ├── state.cpp │ ├── state.h │ ├── table.conf.in.in │ ├── wanfeng.conf.in.in │ ├── wbpy.conf.in.in │ ├── wbx.conf.in.in │ └── zrm.conf.in.in ├── modules ├── CMakeLists.txt ├── chttrans │ ├── CMakeLists.txt │ ├── chttrans-native.cpp │ ├── chttrans-native.h │ ├── chttrans-opencc.cpp │ ├── chttrans-opencc.h │ ├── chttrans.conf.in.in │ ├── chttrans.cpp │ ├── chttrans.h │ ├── gbks2t.tab │ ├── opencc-profile-name.cpp │ └── update-opencc-profile-name.sh ├── cloudpinyin │ ├── CMakeLists.txt │ ├── cloudpinyin.conf.in.in │ ├── cloudpinyin.cpp │ ├── cloudpinyin.h │ ├── cloudpinyin_public.h │ ├── fetch.cpp │ ├── fetch.h │ └── lrucache.h ├── fullwidth │ ├── CMakeLists.txt │ ├── fullwidth.conf.in.in │ ├── fullwidth.cpp │ └── fullwidth.h ├── pinyinhelper │ ├── CMakeLists.txt │ ├── pinyinhelper.conf.in.in │ ├── pinyinhelper.cpp │ ├── pinyinhelper.h │ ├── pinyinhelper_public.h │ ├── pinyinlookup.cpp │ ├── pinyinlookup.h │ ├── stroke.cpp │ └── stroke.h └── punctuation │ ├── CMakeLists.txt │ ├── punc.mb.zh_CN │ ├── punc.mb.zh_HK │ ├── punc.mb.zh_TW │ ├── punctuation.conf.in.in │ ├── punctuation.cpp │ ├── punctuation.h │ └── punctuation_public.h ├── org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml.in ├── po ├── CMakeLists.txt ├── LINGUAS ├── ca.po ├── da.po ├── de.po ├── fcitx5-chinese-addons.pot ├── he.po ├── ja.po ├── ko.po ├── ru.po ├── vi.po ├── zh_CN.po └── zh_TW.po ├── test ├── CMakeLists.txt ├── addon │ └── CMakeLists.txt ├── inputmethod │ ├── CMakeLists.txt │ ├── sim.conf │ └── trad.conf ├── testchttrans.cpp ├── testcloudpinyin.cpp ├── testcustomphrase.cpp ├── testdir.h.in ├── testfullwidth.cpp ├── testpinyin.cpp ├── testpinyinhelper.cpp ├── testpunctuation.cpp ├── testsymboldictionary.cpp ├── testtable.cpp └── valgrind_suppress └── tools ├── CMakeLists.txt └── scel2org5.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -4 5 | ConstructorInitializerIndentWidth: 4 6 | AlignEscapedNewlinesLeft: false 7 | AlignTrailingComments: true 8 | AllowAllParametersOfDeclarationOnNextLine: true 9 | AllowShortBlocksOnASingleLine: false 10 | AllowShortIfStatementsOnASingleLine: false 11 | AllowShortLoopsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: All 13 | AlwaysBreakTemplateDeclarations: true 14 | AlwaysBreakBeforeMultilineStrings: false 15 | BreakBeforeBinaryOperators: false 16 | BreakBeforeTernaryOperators: true 17 | BreakConstructorInitializersBeforeComma: false 18 | BinPackParameters: true 19 | ColumnLimit: 80 20 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 21 | DerivePointerAlignment: false 22 | ExperimentalAutoDetectBinPacking: false 23 | IndentCaseLabels: false 24 | IndentWrappedFunctionNames: false 25 | IndentFunctionDeclarationAfterType: false 26 | MaxEmptyLinesToKeep: 1 27 | KeepEmptyLinesAtTheStartOfBlocks: true 28 | NamespaceIndentation: None 29 | ObjCSpaceAfterProperty: false 30 | ObjCSpaceBeforeProtocolList: true 31 | PenaltyBreakBeforeFirstCallParameter: 19 32 | PenaltyBreakComment: 300 33 | PenaltyBreakString: 1000 34 | PenaltyBreakFirstLessLess: 120 35 | PenaltyExcessCharacter: 1000000 36 | PenaltyReturnTypeOnItsOwnLine: 60 37 | PointerAlignment: Right 38 | SpacesBeforeTrailingComments: 1 39 | Cpp11BracedListStyle: true 40 | Standard: Cpp11 41 | IndentWidth: 4 42 | TabWidth: 4 43 | UseTab: Never 44 | BreakBeforeBraces: Attach 45 | SpacesInParentheses: false 46 | SpacesInAngles: false 47 | SpaceInEmptyParentheses: false 48 | SpacesInCStyleCastParentheses: false 49 | SpacesInContainerLiterals: true 50 | SpaceBeforeAssignmentOperators: true 51 | ContinuationIndentWidth: 4 52 | CommentPragmas: '^ IWYU pragma:' 53 | ForEachMacros: [ Q_FOREACH, BOOST_FOREACH ] 54 | SpaceBeforeParens: ControlStatements 55 | DisableFormat: false 56 | SortIncludes: true 57 | ... 58 | 59 | -------------------------------------------------------------------------------- /.formatignore: -------------------------------------------------------------------------------- 1 | opencc-profile-name.cpp 2 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | clang-format: 11 | name: Check clang-format 12 | runs-on: ubuntu-latest 13 | container: archlinux:latest 14 | steps: 15 | - name: Install dependencies 16 | run: | 17 | pacman -Syu --noconfirm git clang diffutils 18 | git config --global --add safe.directory $GITHUB_WORKSPACE 19 | - uses: actions/checkout@v4 20 | - uses: fcitx/github-actions@clang-format 21 | check: 22 | name: Build and test 23 | needs: clang-format 24 | runs-on: ubuntu-latest 25 | container: archlinux:latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | compiler: [gcc, clang] 30 | include: 31 | - compiler: gcc 32 | cxx_compiler: g++ 33 | - compiler: clang 34 | cxx_compiler: clang++ 35 | env: 36 | CC: ${{ matrix.compiler }} 37 | CXX: ${{ matrix.cxx_compiler }} 38 | steps: 39 | - name: Install dependencies 40 | run: | 41 | pacman -Syu --noconfirm base-devel clang cmake ninja extra-cmake-modules fmt libuv boost git qt6-base qt6-wayland libxkbcommon qt6-webengine lua opencc 42 | - uses: actions/checkout@v4 43 | with: 44 | repository: fcitx/fcitx5 45 | path: fcitx5 46 | - name: Cache fcitx5 data files 47 | uses: actions/cache@v4 48 | with: 49 | path: 'fcitx5/**/*.tar.*' 50 | key: ${{ runner.os }}-${{ hashFiles('fcitx5/src/modules/spell/CMakeLists.txt') 51 | }} 52 | - name: Build and Install fcitx5 53 | uses: fcitx/github-actions@cmake 54 | with: 55 | path: fcitx5 56 | cmake-option: >- 57 | -DENABLE_KEYBOARD=Off -DENABLE_X11=Off -DENABLE_WAYLAND=Off -DENABLE_ENCHANT=Off 58 | -DENABLE_DBUS=Off -DENABLE_SERVER=Off -DENABLE_EMOJI=Off -DUSE_SYSTEMD=Off 59 | - uses: actions/checkout@v4 60 | with: 61 | repository: fcitx/libime 62 | path: libime 63 | submodules: true 64 | - name: Cache libime data files 65 | uses: actions/cache@v4 66 | with: 67 | path: 'libime/**/*.tar.*' 68 | key: ${{ runner.os }}-${{ hashFiles('libime/data/CMakeLists.txt') }} 69 | - name: Build and Install libime 70 | uses: fcitx/github-actions@cmake 71 | with: 72 | path: libime 73 | - uses: actions/checkout@v4 74 | with: 75 | repository: fcitx/fcitx5-lua 76 | path: fcitx5-lua 77 | - name: Build and Install fcitx5-lua 78 | uses: fcitx/github-actions@cmake 79 | with: 80 | path: fcitx5-lua 81 | - uses: actions/checkout@v4 82 | with: 83 | repository: fcitx/fcitx5-qt 84 | path: fcitx5-qt 85 | - name: Build and Install fcitx5-qt 86 | uses: fcitx/github-actions@cmake 87 | with: 88 | path: fcitx5-qt 89 | cmake-option: >- 90 | -DENABLE_QT4=Off -DENABLE_QT5=Off -DENABLE_QT6=On 91 | - uses: actions/checkout@v4 92 | with: 93 | path: fcitx5-chinese-addons 94 | - name: Init CodeQL 95 | uses: github/codeql-action/init@v3 96 | with: 97 | languages: cpp 98 | source-root: fcitx5-chinese-addons 99 | - name: Build and Install fcitx5-chinese-addons 100 | uses: fcitx/github-actions@cmake 101 | with: 102 | path: fcitx5-chinese-addons 103 | - name: Test 104 | run: | 105 | ctest --test-dir fcitx5-chinese-addons/build 106 | - name: CodeQL Analysis 107 | uses: github/codeql-action/analyze@v2 108 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | .* 3 | !.git* 4 | .git/ 5 | *.tar.* 6 | *.kdev4 7 | *.kate-swp 8 | *.orig 9 | tags 10 | astyle.sh 11 | cscope.* 12 | *.part 13 | XF86keysym.h 14 | keysymdef.h 15 | *~ 16 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6.0) 2 | project(fcitx5-chinese-addons VERSION 5.1.8) 3 | 4 | set(REQUIRED_FCITX_VERSION 5.1.13) 5 | 6 | find_package(ECM REQUIRED 1.0.0) 7 | set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) 8 | include(FeatureSummary) 9 | include(GNUInstallDirs) 10 | include(ECMSetupVersion) 11 | include(ECMUninstallTarget) 12 | 13 | find_package(Fcitx5Core ${REQUIRED_FCITX_VERSION} REQUIRED) 14 | find_package(Fcitx5Module REQUIRED COMPONENTS Notifications QuickPhrase Spell Clipboard) 15 | find_package(Fcitx5ModuleLuaAddonLoader) 16 | find_package(Pthread REQUIRED) 17 | find_package(PkgConfig REQUIRED) 18 | find_package(Gettext REQUIRED) 19 | 20 | include("${FCITX_INSTALL_CMAKECONFIG_DIR}/Fcitx5Utils/Fcitx5CompilerSettings.cmake") 21 | 22 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") 23 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 24 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 25 | 26 | ####################################################################### 27 | # Options 28 | ####################################################################### 29 | option(ENABLE_TEST "Build Test" On) 30 | option(ENABLE_COVERAGE "Build the project with gcov support (Need ENABLE_TEST=On)" Off) 31 | set(GCOV_TOOL "gcov" CACHE STRING "Path to gcov tool used by coverage.") 32 | option(ENABLE_OPENCC "Enable OpenCC for chttrans" On) 33 | option(ENABLE_GUI "Enable Configure Gui" On) 34 | option(ENABLE_BROWSER "Enable built-in browser." On) 35 | option(ENABLE_CLOUDPINYIN "Build cloud pinyin addon" On) 36 | option(ENABLE_DATA "Build data" On) 37 | 38 | if (ENABLE_OPENCC) 39 | find_package(OpenCC 1.0.1 REQUIRED) 40 | endif() 41 | 42 | if (ENABLE_GUI) 43 | set(QT_MAJOR_VERSION 6) 44 | find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS Concurrent) 45 | find_package(Fcitx5Qt${QT_MAJOR_VERSION}WidgetsAddons REQUIRED) 46 | if (ENABLE_BROWSER) 47 | find_package(Qt${QT_MAJOR_VERSION}WebEngineWidgets REQUIRED) 48 | endif() 49 | endif() 50 | 51 | # We do not need json if OpenCC is not needed, but just try to find it anyway to save some ifelse logic 52 | find_package(Boost 1.61 OPTIONAL_COMPONENTS json) 53 | find_package(LibIMEPinyin 1.1.11 REQUIRED) 54 | find_package(LibIMETable 1.1.4 REQUIRED) 55 | 56 | if (ENABLE_CLOUDPINYIN) 57 | pkg_check_modules(Curl REQUIRED IMPORTED_TARGET "libcurl") 58 | endif() 59 | 60 | if (TARGET Boost::json) 61 | set(HAS_BOOST_JSON TRUE) 62 | endif() 63 | 64 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) 65 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 66 | 67 | add_definitions(-DFCITX_GETTEXT_DOMAIN=\"fcitx5-chinese-addons\") 68 | add_definitions(-DQT_NO_KEYWORDS) 69 | fcitx5_add_i18n_definition() 70 | 71 | add_subdirectory(modules) 72 | add_subdirectory(im) 73 | add_subdirectory(po) 74 | add_subdirectory(tools) 75 | 76 | if (ENABLE_GUI) 77 | add_subdirectory(gui) 78 | endif() 79 | 80 | add_subdirectory(icon) 81 | 82 | if (ENABLE_TEST) 83 | find_package(Fcitx5ModuleTestFrontend REQUIRED) 84 | find_package(Fcitx5ModuleTestIM REQUIRED) 85 | enable_testing() 86 | add_subdirectory(test) 87 | 88 | if (ENABLE_COVERAGE) 89 | add_custom_target(coverage 90 | COMMAND "${CMAKE_CTEST_COMMAND}" 91 | COMMAND lcov --gcov-tool "${GCOV_TOOL}" --no-external --capture --directory ./ -b "${CMAKE_CURRENT_SOURCE_DIR}" --output-file coverage.info 92 | COMMAND genhtml coverage.info --output-directory "coverage_pages" 93 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 94 | endif() 95 | endif () 96 | 97 | fcitx5_translate_desktop_file(org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml.in 98 | org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml XML) 99 | 100 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml" DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo) 101 | 102 | feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) 103 | -------------------------------------------------------------------------------- /COPYING.unicode: -------------------------------------------------------------------------------- 1 | UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE 2 | 3 | Unicode Data Files include all data files under the directories 4 | http://www.unicode.org/Public/, http://www.unicode.org/reports/, 5 | http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, 6 | and http://www.unicode.org/utility/trac/browser/. 7 | 8 | Unicode Data Files do not include PDF online code charts under the 9 | directory http://www.unicode.org/Public/. 10 | 11 | Software includes any source code published in the Unicode Standard 12 | or under the directories 13 | http://www.unicode.org/Public/, http://www.unicode.org/reports/, 14 | http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, 15 | and http://www.unicode.org/utility/trac/browser/. 16 | 17 | NOTICE TO USER: Carefully read the following legal agreement. 18 | BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA 19 | FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, 20 | AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. 21 | IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE 22 | DATA FILES OR SOFTWARE. 23 | 24 | COPYRIGHT AND PERMISSION NOTICE 25 | 26 | Copyright © 1991-2016 Unicode, Inc. All rights reserved. Distributed under 27 | the Terms of Use in http://www.unicode.org/copyright.html. 28 | 29 | Permission is hereby granted, free of charge, to any person obtaining a copy 30 | of the Unicode data files and any associated documentation (the "Data Files") 31 | or Unicode software and any associated documentation (the "Software") to deal 32 | in the Data Files or Software without restriction, including without 33 | limitation the rights to use, copy, modify, merge, publish, distribute, 34 | and/or sell copies of the Data Files or Software, and to permit persons to 35 | whom the Data Files or Software are furnished to do so, provided that either 36 | (a) this copyright and permission notice appear with all copies of the Data 37 | Files or Software, or 38 | (b) this copyright and permission notice appear in associated Documentation. 39 | 40 | THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 41 | KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 42 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF 43 | THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS 44 | INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR 45 | CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 46 | DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 47 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 48 | OF THE DATA FILES OR SOFTWARE. 49 | 50 | Except as contained in this notice, the name of a copyright holder shall not 51 | be used in advertising or otherwise to promote the sale, use or other 52 | dealings in these Data Files or Software without prior written authorization 53 | of the copyright holder. 54 | -------------------------------------------------------------------------------- /Messages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gen_pot cxx:ui:desktop:appdata:sh fcitx5-chinese-addons po . 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Chinese related addon for fcitx5 2 | ================================================ 3 | This provides pinyin and table input method support for fcitx5. Released 4 | under LGPL-2.1+. 5 | 6 | im/pinyin/emoji.txt is derived from Unicode CLDR with modification. 7 | 8 | [![Jenkins Build Status](https://img.shields.io/jenkins/s/https/jenkins.fcitx-im.org/job/fcitx5-chinese-addons.svg)](https://jenkins.fcitx-im.org/job/fcitx5-chinese-addons/) 9 | 10 | [![Coverity Scan Status](https://img.shields.io/coverity/scan/11995.svg)](https://scan.coverity.com/projects/fcitx-fcitx5-chinese-addons) 11 | -------------------------------------------------------------------------------- /cmake/FindOpenCC.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | 3 | pkg_check_modules(PKG_OPENCC QUIET opencc) 4 | 5 | set(OPENCC_DEFINITIONS ${PKG_OPENCC_CFLAGS_OTHER}) 6 | set(OPENCC_VERSION ${PKG_OPENCC_VERSION}) 7 | set(OPENCC_PREFIX ${PKG_OPENCC_PREFIX}) 8 | 9 | find_path(OPENCC_INCLUDE_DIR 10 | NAMES opencc.h 11 | HINTS ${PKG_OPENCC_INCLUDE_DIRS} 12 | ) 13 | find_library(OPENCC_LIBRARY 14 | NAMES opencc 15 | HINTS ${PKG_OPENCC_LIBRARY_DIRS} 16 | ) 17 | 18 | include(FindPackageHandleStandardArgs) 19 | find_package_handle_standard_args(OpenCC 20 | FOUND_VAR 21 | OPENCC_FOUND 22 | REQUIRED_VARS 23 | OPENCC_LIBRARY 24 | OPENCC_INCLUDE_DIR 25 | OPENCC_PREFIX 26 | VERSION_VAR 27 | OPENCC_VERSION 28 | ) 29 | 30 | if(OPENCC_FOUND AND NOT TARGET OpenCC::OpenCC) 31 | add_library(OpenCC::OpenCC UNKNOWN IMPORTED) 32 | set_target_properties(OpenCC::OpenCC PROPERTIES 33 | IMPORTED_LOCATION "${OPENCC_LIBRARY}" 34 | INTERFACE_COMPILE_OPTIONS "${OPENCC_DEFINITIONS}" 35 | INTERFACE_INCLUDE_DIRECTORIES "${OPENCC_INCLUDE_DIR}" 36 | ) 37 | endif() 38 | 39 | mark_as_advanced(OPENCC_INCLUDE_DIR OPENCC_LIBRARY) 40 | 41 | include(FeatureSummary) 42 | set_package_properties(OPENCC PROPERTIES 43 | URL "https://github.com/BYVoid/OpenCC/" 44 | DESCRIPTION "Library for Open Chinese Convert" 45 | ) 46 | 47 | -------------------------------------------------------------------------------- /cmake/FindPthread.cmake: -------------------------------------------------------------------------------- 1 | # Try to find Pthread functionality 2 | # Once done this will define 3 | # 4 | # PTHREAD_FOUND - system has Pthread 5 | # PTHREAD_INCLUDE_DIR - Pthread include directory 6 | # PTHREAD_LIBRARIES - Libraries needed to use Pthread 7 | # 8 | # TODO: This will enable translations only if Gettext functionality is 9 | # present in libc. Must have more robust system for release, where Gettext 10 | # functionality can also reside in standalone Gettext library, or the one 11 | # embedded within kdelibs (cf. gettext.m4 from Gettext source). 12 | # 13 | # Copyright (c) 2006, Chusslove Illich, 14 | # Copyright (c) 2007, Alexander Neundorf, 15 | # Copyright (c) 2016, Xuetian Weng 16 | # 17 | # Redistribution and use is allowed according to the terms of the BSD license. 18 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 19 | 20 | find_path(PTHREAD_INCLUDE_DIR NAMES pthread.h) 21 | 22 | if(PTHREAD_INCLUDE_DIR) 23 | include(CheckFunctionExists) 24 | check_function_exists(pthread_create PTHREAD_LIBC_HAS_PTHREAD_CREATE) 25 | 26 | if (PTHREAD_LIBC_HAS_PTHREAD_CREATE) 27 | set(PTHREAD_LIBRARIES) 28 | set(PTHREAD_LIB_FOUND TRUE) 29 | else (PTHREAD_LIBC_HAS_PTHREAD_CREATE) 30 | find_library(PTHREAD_LIBRARIES NAMES pthread libpthread ) 31 | if(PTHREAD_LIBRARIES) 32 | set(PTHREAD_LIB_FOUND TRUE) 33 | endif(PTHREAD_LIBRARIES) 34 | endif (PTHREAD_LIBC_HAS_PTHREAD_CREATE) 35 | 36 | endif(PTHREAD_INCLUDE_DIR) 37 | 38 | include(FindPackageHandleStandardArgs) 39 | find_package_handle_standard_args(Pthread 40 | FOUND_VAR 41 | PTHREAD_FOUND 42 | REQUIRED_VARS 43 | PTHREAD_INCLUDE_DIR PTHREAD_LIB_FOUND 44 | ) 45 | 46 | if(PTHREAD_FOUND AND NOT TARGET Pthread::Pthread) 47 | if (PTHREAD_LIBRARIES) 48 | add_library(Pthread::Pthread UNKNOWN IMPORTED) 49 | set_target_properties(Pthread::Pthread PROPERTIES 50 | IMPORTED_LOCATION "${PTHREAD_LIBRARIES}") 51 | else() 52 | add_library(Pthread::Pthread INTERFACE IMPORTED ) 53 | endif() 54 | set_target_properties(Pthread::Pthread PROPERTIES 55 | INTERFACE_INCLUDE_DIRECTORIES "${PTHREAD_INCLUDE_DIR}" 56 | ) 57 | endif() 58 | 59 | mark_as_advanced(PTHREAD_INCLUDE_DIR PTHREAD_LIBRARIES PTHREAD_LIBC_HAS_PTHREAD_CREATE PTHREAD_LIB_FOUND) 60 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _FCITX5_CHINESE_ADDONS_CONFIG_H_IN_ 8 | #define _FCITX5_CHINESE_ADDONS_CONFIG_H_IN_ 9 | 10 | #cmakedefine ENABLE_OPENCC 11 | #cmakedefine ENABLE_BROWSER 12 | #cmakedefine HAS_BOOST_JSON 13 | #cmakedefine OPENCC_PREFIX "@OPENCC_PREFIX@" 14 | #define LIBIME_INSTALL_PKGDATADIR "@LIBIME_INSTALL_PKGDATADIR@" 15 | 16 | #ifndef _GNU_SOURCE 17 | #define _GNU_SOURCE 18 | #endif 19 | 20 | #endif // _FCITX5_CHINESE_ADDONS_CONFIG_H_IN_ 21 | -------------------------------------------------------------------------------- /gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(pinyindictmanager) 2 | add_subdirectory(customphraseeditor) -------------------------------------------------------------------------------- /gui/customphraseeditor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CUSTOMPHRASEEDITOR_SOURCES 2 | main.cpp 3 | customphraseeditor.cpp 4 | customphrasemodel.cpp 5 | editordialog.cpp 6 | ../../im/pinyin/customphrase.cpp 7 | ) 8 | 9 | add_library(customphraseeditor MODULE ${CUSTOMPHRASEEDITOR_SOURCES}) 10 | target_link_libraries(customphraseeditor Fcitx5Qt${QT_MAJOR_VERSION}::WidgetsAddons ${BROWSER_TARGET} Qt${QT_MAJOR_VERSION}::Concurrent LibIME::Core) 11 | set_target_properties(customphraseeditor PROPERTIES AUTOMOC TRUE AUTOUIC TRUE AUTOUIC_OPTIONS "-tr=fcitx::tr2fcitx;--include=fcitxqti18nhelper.h") 12 | 13 | install(TARGETS customphraseeditor DESTINATION ${CMAKE_INSTALL_LIBDIR}/fcitx5/qt${QT_MAJOR_VERSION}) 14 | -------------------------------------------------------------------------------- /gui/customphraseeditor/customphraseeditor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023~2023 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _CUSTOMPHRASEEDITOR_CUSTOMPHRASEEDITOR_H_ 8 | #define _CUSTOMPHRASEEDITOR_CUSTOMPHRASEEDITOR_H_ 9 | 10 | #include "customphrasemodel.h" 11 | #include "ui_customphraseeditor.h" 12 | #include 13 | #include 14 | 15 | namespace fcitx { 16 | 17 | class CustomPhraseEditor : public FcitxQtConfigUIWidget, 18 | public Ui::CustomPhraseEditor { 19 | Q_OBJECT 20 | public: 21 | CustomPhraseEditor(QWidget *parent); 22 | 23 | void load() override; 24 | void save() override; 25 | QString title() override; 26 | bool asyncSave() override; 27 | QString icon() override { return "fcitx-pinyin"; } 28 | 29 | private Q_SLOTS: 30 | void addPhrase(); 31 | void addPhraseAccepted(); 32 | void removePhrase(); 33 | void clear(); 34 | void openExternal(); 35 | 36 | private: 37 | void updated(); 38 | void connectFileWatcher(); 39 | void disconnectFileWatcher(); 40 | 41 | CustomPhraseModel *model_; 42 | QFileSystemWatcher watcher_; 43 | QString userFile_; 44 | }; 45 | 46 | } // namespace fcitx 47 | 48 | #endif // _CUSTOMPHRASEEDITOR_CUSTOMPHRASEEDITOR_H_ 49 | -------------------------------------------------------------------------------- /gui/customphraseeditor/customphraseeditor.json: -------------------------------------------------------------------------------- 1 | { 2 | "addon": "pinyin", 3 | "files": ["customphrase"] 4 | } 5 | 6 | -------------------------------------------------------------------------------- /gui/customphraseeditor/customphraseeditor.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CustomPhraseEditor 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 600 11 | 12 | 13 | 14 | 15 | 600 16 | 400 17 | 18 | 19 | 20 | 21 | 22 | 23 | QAbstractItemView::SingleSelection 24 | 25 | 26 | QAbstractItemView::SelectRows 27 | 28 | 29 | true 30 | 31 | 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | &Add 42 | 43 | 44 | 45 | .. 46 | 47 | 48 | 49 | 50 | 51 | 52 | &Remove 53 | 54 | 55 | 56 | .. 57 | 58 | 59 | 60 | 61 | 62 | 63 | &Usage 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | &External Editor 74 | 75 | 76 | 77 | .. 78 | 79 | 80 | 81 | 82 | 83 | 84 | &Clear 85 | 86 | 87 | 88 | .. 89 | 90 | 91 | 92 | 93 | 94 | 95 | Qt::Vertical 96 | 97 | 98 | 99 | 20 100 | 40 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /gui/customphraseeditor/customphrasemodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023~2023 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _CUSTOMPHRASEEDITOR_MODEL_H_ 8 | #define _CUSTOMPHRASEEDITOR_MODEL_H_ 9 | 10 | #include "../../im/pinyin/customphrase.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace fcitx { 19 | 20 | struct CustomPhraseItem { 21 | QString key; 22 | QString value; 23 | int order; 24 | bool enabled; 25 | }; 26 | 27 | class CustomPhraseModel : public QAbstractTableModel { 28 | Q_OBJECT 29 | public: 30 | enum { Column_Enable = 0, Column_Key, Column_Phrase, Column_Order }; 31 | explicit CustomPhraseModel(QObject *parent = 0); 32 | virtual ~CustomPhraseModel(); 33 | 34 | Qt::ItemFlags flags(const QModelIndex &index) const override; 35 | bool setData(const QModelIndex &index, const QVariant &value, 36 | int role = Qt::EditRole) override; 37 | QVariant headerData(int section, Qt::Orientation orientation, 38 | int role = Qt::DisplayRole) const override; 39 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 40 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 41 | QVariant data(const QModelIndex &index, 42 | int role = Qt::DisplayRole) const override; 43 | void addItem(const QString &key, const QString &value, int order, 44 | bool enabled); 45 | void deleteItem(int row); 46 | void deleteAllItem(); 47 | QFutureWatcher *save(); 48 | bool needSave(); 49 | void load(); 50 | 51 | Q_SIGNALS: 52 | void needSaveChanged(bool needSave); 53 | 54 | private Q_SLOTS: 55 | void loadFinished(); 56 | void saveFinished(); 57 | void setNeedSave(bool needSave); 58 | 59 | private: 60 | static QList parse(const QString &file); 61 | static bool saveData(const QString &file, 62 | const QList &list); 63 | QList list_; 64 | bool needSave_ = false; 65 | QFutureWatcher> *futureWatcher_ = nullptr; 66 | }; 67 | 68 | std::string customPhraseHelpMessage(); 69 | 70 | static inline constexpr char customPhraseFileName[] = "pinyin/customphrase"; 71 | 72 | } // namespace fcitx 73 | 74 | #endif // _CUSTOMPHRASEEDITOR_MODEL_H_ 75 | -------------------------------------------------------------------------------- /gui/customphraseeditor/editordialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017~2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "editordialog.h" 9 | #include 10 | 11 | namespace fcitx { 12 | EditorDialog::EditorDialog(QWidget *parent) : QDialog(parent) { setupUi(this); } 13 | 14 | EditorDialog::~EditorDialog() {} 15 | 16 | void EditorDialog::setKey(const QString &s) { keyLineEdit->setText(s); } 17 | 18 | void EditorDialog::setValue(const QString &s) { valueLineEdit->setText(s); } 19 | 20 | void EditorDialog::setOrder(int order) { orderSpinBox->setValue(order); } 21 | 22 | QString EditorDialog::key() const { return keyLineEdit->text(); } 23 | 24 | QString EditorDialog::value() const { return valueLineEdit->text(); } 25 | 26 | int EditorDialog::order() const { return orderSpinBox->value(); } 27 | } // namespace fcitx 28 | -------------------------------------------------------------------------------- /gui/customphraseeditor/editordialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2012~2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _QUICKPHRASE_EDITOR_EDITORDIALOG_H_ 8 | #define _QUICKPHRASE_EDITOR_EDITORDIALOG_H_ 9 | 10 | #include "ui_editordialog.h" 11 | #include 12 | 13 | namespace fcitx { 14 | class EditorDialog : public QDialog, public Ui::EditorDialog { 15 | Q_OBJECT 16 | public: 17 | explicit EditorDialog(QWidget *parent = 0); 18 | virtual ~EditorDialog(); 19 | 20 | QString key() const; 21 | QString value() const; 22 | int order() const; 23 | void setValue(const QString &s); 24 | void setKey(const QString &s); 25 | void setOrder(int order); 26 | }; 27 | } // namespace fcitx 28 | 29 | #endif // _QUICKPHRASE_EDITOR_EDITORDIALOG_H_ 30 | -------------------------------------------------------------------------------- /gui/customphraseeditor/editordialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | EditorDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 334 10 | 170 11 | 12 | 13 | 14 | Add Phrase 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Keyword: 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Phrase: 36 | 37 | 38 | 39 | 40 | 41 | 42 | 1 43 | 44 | 45 | 100 46 | 47 | 48 | 1 49 | 50 | 51 | 52 | 53 | 54 | 55 | Order: 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Qt::Horizontal 65 | 66 | 67 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 68 | 69 | 70 | 71 | 72 | 73 | 74 | keyLineEdit 75 | 76 | 77 | 78 | 79 | buttonBox 80 | accepted() 81 | EditorDialog 82 | accept() 83 | 84 | 85 | 248 86 | 254 87 | 88 | 89 | 157 90 | 274 91 | 92 | 93 | 94 | 95 | buttonBox 96 | rejected() 97 | EditorDialog 98 | reject() 99 | 100 | 101 | 316 102 | 260 103 | 104 | 105 | 286 106 | 274 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /gui/customphraseeditor/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023~2023 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "main.h" 9 | #include "customphraseeditor.h" 10 | #include 11 | 12 | namespace fcitx { 13 | 14 | CustomPhraseEditorPlugin::CustomPhraseEditorPlugin(QObject *parent) 15 | : FcitxQtConfigUIPlugin(parent) { 16 | registerDomain("fcitx5-chinese-addons", FCITX_INSTALL_LOCALEDIR); 17 | } 18 | 19 | FcitxQtConfigUIWidget *CustomPhraseEditorPlugin::create(const QString &key) { 20 | Q_UNUSED(key); 21 | return new CustomPhraseEditor(nullptr); 22 | } 23 | 24 | } // namespace fcitx 25 | -------------------------------------------------------------------------------- /gui/customphraseeditor/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023~2023 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _CUSTOMPHRASEEDITOR_MAIN_H_ 8 | #define _CUSTOMPHRASEEDITOR_MAIN_H_ 9 | 10 | #include "fcitxqtconfiguiplugin.h" 11 | 12 | namespace fcitx { 13 | 14 | class CustomPhraseEditorPlugin : public FcitxQtConfigUIPlugin { 15 | Q_OBJECT 16 | public: 17 | Q_PLUGIN_METADATA(IID FcitxQtConfigUIFactoryInterface_iid FILE 18 | "customphraseeditor.json") 19 | explicit CustomPhraseEditorPlugin(QObject *parent = nullptr); 20 | FcitxQtConfigUIWidget *create(const QString &key) override; 21 | }; 22 | 23 | } // namespace fcitx 24 | 25 | #endif // _CUSTOMPHRASEEDITOR_MAIN_H_ 26 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(DICTMANAGER_SOURCES 2 | main.cpp 3 | pinyindictmanager.cpp 4 | processrunner.cpp 5 | pipeline.cpp 6 | pipelinejob.cpp 7 | log.cpp 8 | renamefile.cpp 9 | filelistmodel.cpp 10 | ) 11 | 12 | if (ENABLE_BROWSER) 13 | list(APPEND DICTMANAGER_SOURCES browserdialog.cpp filedownloader.cpp) 14 | set(BROWSER_TARGET Qt${QT_MAJOR_VERSION}::WebEngineWidgets) 15 | endif() 16 | 17 | add_library(pinyindictmanager MODULE ${DICTMANAGER_SOURCES}) 18 | target_link_libraries(pinyindictmanager Fcitx5Qt${QT_MAJOR_VERSION}::WidgetsAddons ${BROWSER_TARGET} Qt${QT_MAJOR_VERSION}::Concurrent) 19 | set_target_properties(pinyindictmanager PROPERTIES AUTOMOC TRUE AUTOUIC TRUE AUTOUIC_OPTIONS "-tr=fcitx::tr2fcitx;--include=fcitxqti18nhelper.h") 20 | 21 | install(TARGETS pinyindictmanager DESTINATION ${CMAKE_INSTALL_LIBDIR}/fcitx5/qt${QT_MAJOR_VERSION}) 22 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/browserdialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2013-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "browserdialog.h" 9 | #include "guicommon.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace fcitx { 22 | 23 | using WebPageBase = QWebEnginePage; 24 | using WebViewType = QWebEngineView; 25 | 26 | /* 27 | * a typical link looks like this. 28 | * http://download.pinyin.sogou.com/dict/download_cell.php?id=15207&name=%D6%B2%CE%EF%B4%CA%BB%E3%B4%F3%C8%AB%A1%BE%B9%D9%B7%BD%CD%C6%BC%F6%A1%BF 29 | */ 30 | 31 | class WebPage : public WebPageBase { 32 | public: 33 | WebPage(BrowserDialog *dialog) : WebPageBase(dialog), dialog_(dialog) {} 34 | 35 | protected: 36 | bool acceptNavigationRequest(const QUrl &url, NavigationType /*type*/, 37 | bool /*isMainFrame*/) override { 38 | return dialog_->linkClicked(url); 39 | } 40 | 41 | WebPageBase *createWindow(WebPageBase::WebWindowType /*type*/) override { 42 | return this; 43 | } 44 | 45 | private: 46 | BrowserDialog *dialog_; 47 | }; 48 | 49 | BrowserDialog::BrowserDialog(QWidget *parent) 50 | : QDialog(parent), page_(new WebPage(this)) { 51 | setupUi(this); 52 | webView_->setPage(page_); 53 | setWindowIcon(QIcon::fromTheme("internet-web-browser")); 54 | setWindowTitle(_("Browse Sogou Cell Dict repository")); 55 | 56 | connect(webView_, &WebViewType::loadProgress, progressBar_, 57 | &QProgressBar::setValue); 58 | connect(webView_, &WebViewType::loadStarted, progressBar_, 59 | &QProgressBar::show); 60 | connect(webView_, &WebViewType::loadFinished, progressBar_, 61 | &QProgressBar::hide); 62 | webView_->load(QUrl(URL_BASE)); 63 | } 64 | 65 | BrowserDialog::~BrowserDialog() {} 66 | 67 | QString BrowserDialog::decodeName(const QByteArray &in) { 68 | QByteArray out = QByteArray::fromPercentEncoding(in); 69 | return QString::fromUtf8(out); 70 | } 71 | 72 | bool BrowserDialog::linkClicked(const QUrl &url) { 73 | do { 74 | if (url.host() != DOWNLOAD_HOST_BASE && url.host() != HOST_BASE) { 75 | break; 76 | } 77 | 78 | // Now the site seems to have "d/dict/download_cell.php", just to make 79 | // it works with both. 80 | if (!url.path().endsWith("/dict/download_cell.php")) { 81 | break; 82 | } 83 | QUrlQuery query(url); 84 | QString id = query.queryItemValue("id"); 85 | QByteArray name = 86 | query.queryItemValue("name", QUrl::FullyEncoded).toLatin1(); 87 | QString sname = decodeName(name); 88 | 89 | name_ = sname; 90 | url_ = url; 91 | 92 | if (!id.isEmpty() && !sname.isEmpty()) { 93 | accept(); 94 | return false; 95 | } 96 | } while (0); 97 | 98 | if (url.host() != HOST_BASE) { 99 | QMessageBox::information(this, _("Wrong Link"), 100 | _("No browsing outside pinyin.sogou.com, now " 101 | "redirect to home page.")); 102 | webView_->load(QUrl(URL_BASE)); 103 | return false; 104 | } 105 | return true; 106 | } 107 | 108 | } // namespace fcitx 109 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/browserdialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2013-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_BROWSERDIALOG_H_ 8 | #define _PINYINDICTMANAGER_BROWSERDIALOG_H_ 9 | 10 | #include "config.h" 11 | #include "ui_browserdialog.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace fcitx { 20 | 21 | class WebPage; 22 | 23 | class BrowserDialog : public QDialog, public Ui::BrowserDialog { 24 | friend class WebPage; 25 | Q_OBJECT 26 | public: 27 | explicit BrowserDialog(QWidget *parent = nullptr); 28 | virtual ~BrowserDialog(); 29 | const QUrl &url() const { return url_; } 30 | const QString &name() const { return name_; } 31 | 32 | private: 33 | bool linkClicked(const QUrl &url); 34 | QString decodeName(const QByteArray &in); 35 | QString name_; 36 | QUrl url_; 37 | WebPage *page_; 38 | }; 39 | 40 | } // namespace fcitx 41 | 42 | #endif // _PINYINDICTMANAGER_BROWSERDIALOG_H_ 43 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/browserdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | BrowserDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1200 10 | 600 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | 21 | about:blank 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 24 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | QWebEngineView 38 | QWidget 39 |
QtWebEngineWidgets/QWebEngineView
40 |
41 |
42 | 43 | 44 |
45 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/filedownloader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "filedownloader.h" 9 | #include "pipelinejob.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace fcitx { 18 | 19 | FileDownloader::FileDownloader(const QUrl &url, const QString &dest, 20 | QObject *parent) 21 | : PipelineJob(parent), url_(url), file_(dest), progress_(0) {} 22 | 23 | void FileDownloader::start() { 24 | if (!file_.open(QIODevice::WriteOnly)) { 25 | Q_EMIT message(QMessageBox::Warning, 26 | _("Create temporary file failed.")); 27 | Q_EMIT finished(false); 28 | return; 29 | } 30 | Q_EMIT message(QMessageBox::Information, _("Temporary file created.")); 31 | 32 | QNetworkRequest request(url_); 33 | request.setRawHeader( 34 | "Referer", 35 | QString("%1://%2").arg(url_.scheme()).arg(url_.host()).toLatin1()); 36 | reply_ = nam_.get(request); 37 | 38 | if (!reply_) { 39 | Q_EMIT message(QMessageBox::Warning, _("Failed to create request.")); 40 | Q_EMIT finished(false); 41 | return; 42 | } 43 | Q_EMIT message(QMessageBox::Information, _("Download started.")); 44 | 45 | connect(reply_, &QNetworkReply::readyRead, this, 46 | &FileDownloader::readyToRead); 47 | connect(reply_, &QNetworkReply::finished, this, 48 | &FileDownloader::downloadFinished); 49 | connect(reply_, &QNetworkReply::downloadProgress, this, 50 | &FileDownloader::updateProgress); 51 | } 52 | 53 | void FileDownloader::abort() { 54 | reply_->abort(); 55 | delete reply_; 56 | reply_ = nullptr; 57 | } 58 | 59 | void FileDownloader::cleanUp() { file_.remove(); } 60 | 61 | void FileDownloader::readyToRead() { file_.write(reply_->readAll()); } 62 | 63 | void FileDownloader::updateProgress(qint64 downloaded, qint64 total) { 64 | if (total <= 0) { 65 | return; 66 | } 67 | 68 | int percent = (int)(((qreal)downloaded / total) * 100); 69 | if (percent > 100) { 70 | percent = 100; 71 | } 72 | if (percent >= progress_ + 10) { 73 | Q_EMIT message(QMessageBox::Information, 74 | QString::fromUtf8(_("%1% Downloaded.")).arg(percent)); 75 | progress_ = percent; 76 | } 77 | } 78 | 79 | void FileDownloader::downloadFinished() { 80 | file_.close(); 81 | Q_EMIT message(QMessageBox::Information, _("Download Finished")); 82 | Q_EMIT finished(true); 83 | } 84 | 85 | } // namespace fcitx 86 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/filedownloader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_FILEDOWNLOADER_H_ 8 | #define _PINYINDICTMANAGER_FILEDOWNLOADER_H_ 9 | 10 | #include "pipelinejob.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace fcitx { 20 | 21 | class FileDownloader : public PipelineJob { 22 | Q_OBJECT 23 | public: 24 | explicit FileDownloader(const QUrl &url, const QString &dest, 25 | QObject *parent = nullptr); 26 | 27 | void start() override; 28 | void abort() override; 29 | void cleanUp() override; 30 | 31 | public Q_SLOTS: 32 | void readyToRead(); 33 | void downloadFinished(); 34 | void updateProgress(qint64, qint64); 35 | 36 | private: 37 | QUrl url_; 38 | QFile file_; 39 | QNetworkAccessManager nam_; 40 | QNetworkReply *reply_ = nullptr; 41 | int progress_; 42 | }; 43 | 44 | } // namespace fcitx 45 | 46 | #endif // _PINYINDICTMANAGER_FILEDOWNLOADER_H_ 47 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/filelistmodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2013-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "filelistmodel.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fcitx { 26 | 27 | FileListModel::FileListModel(QObject *parent) : QAbstractListModel(parent) { 28 | loadFileList(); 29 | } 30 | 31 | FileListModel::~FileListModel() {} 32 | 33 | int FileListModel::rowCount(const QModelIndex & /*parent*/) const { 34 | return fileList_.size(); 35 | } 36 | 37 | QVariant FileListModel::data(const QModelIndex &index, int role) const { 38 | if (!index.isValid() || index.row() >= fileList_.size()) { 39 | return {}; 40 | } 41 | 42 | switch (role) { 43 | case Qt::DisplayRole: { 44 | auto name = fileList_[index.row()].first; 45 | 46 | if (name.endsWith(".dict")) { 47 | name = name.left(name.size() - 5); 48 | } 49 | return name; 50 | } 51 | case Qt::CheckStateRole: { 52 | return fileList_[index.row()].second ? Qt::Checked : Qt::Unchecked; 53 | } 54 | case Qt::UserRole: 55 | return fileList_[index.row()].first; 56 | default: 57 | break; 58 | } 59 | return QVariant(); 60 | } 61 | 62 | bool FileListModel::setData(const QModelIndex &index, const QVariant &value, 63 | int role) { 64 | if (!index.isValid() || index.row() >= fileList_.size()) { 65 | return false; 66 | } 67 | 68 | if (role == Qt::CheckStateRole) { 69 | if (fileList_[index.row()].second != value.toBool()) { 70 | fileList_[index.row()].second = value.toBool(); 71 | Q_EMIT changed(); 72 | return true; 73 | } 74 | } 75 | return false; 76 | } 77 | 78 | Qt::ItemFlags FileListModel::flags(const QModelIndex &index) const { 79 | if (!index.isValid() || index.row() >= fileList_.size()) { 80 | return {}; 81 | } 82 | 83 | return Qt::ItemIsUserCheckable | QAbstractListModel::flags(index); 84 | } 85 | 86 | void FileListModel::loadFileList() { 87 | beginResetModel(); 88 | fileList_.clear(); 89 | auto files = StandardPaths::global().locate(StandardPathsType::PkgData, 90 | "pinyin/dictionaries", 91 | pathfilter::extension(".dict")); 92 | std::map enableMap; 93 | for (const auto &file : files) { 94 | enableMap[file.first] = true; 95 | } 96 | auto disableFiles = StandardPaths::global().locate( 97 | StandardPathsType::PkgData, "pinyin/dictionaries", 98 | pathfilter::extension(".disable")); 99 | for (const auto &file : disableFiles) { 100 | // Remove .disable suffix. 101 | QString s = QString::fromStdU16String(file.first.u16string()); 102 | auto dictName = s.chopped(8).toStdU16String(); 103 | if (auto iter = enableMap.find(std::filesystem::path(dictName)); 104 | iter != enableMap.end()) { 105 | iter->second = false; 106 | } 107 | } 108 | for (const auto &file : enableMap) { 109 | fileList_.append({QString::fromStdString(file.first), file.second}); 110 | } 111 | 112 | endResetModel(); 113 | } 114 | 115 | int FileListModel::findFile(const QString &lastFileName) { 116 | auto iter = 117 | std::ranges::find_if(fileList_, [&lastFileName](const auto &item) { 118 | return item.first == lastFileName; 119 | }); 120 | if (iter == fileList_.end()) { 121 | return 0; 122 | } 123 | return std::distance(fileList_.begin(), iter); 124 | } 125 | 126 | void FileListModel::save() { 127 | const auto baseDir = 128 | StandardPaths::global().userDirectory(StandardPathsType::PkgData) / 129 | "pinyin/dictionaries"; 130 | for (const auto &file : fileList_) { 131 | auto disableFilePath = 132 | baseDir / (file.first.toStdString() + ".disable"); 133 | QFile disableFile(QString::fromStdString(disableFilePath)); 134 | if (file.second) { 135 | disableFile.remove(); 136 | } else { 137 | if (fs::makePath(baseDir)) { 138 | disableFile.open(QIODevice::WriteOnly); 139 | disableFile.close(); 140 | } 141 | } 142 | } 143 | } 144 | 145 | } // namespace fcitx 146 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/filelistmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2013-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_FILELISTMODEL_H_ 8 | #define _PINYINDICTMANAGER_FILELISTMODEL_H_ 9 | 10 | #include 11 | #include 12 | 13 | namespace fcitx { 14 | 15 | class FileListModel : public QAbstractListModel { 16 | Q_OBJECT 17 | public: 18 | explicit FileListModel(QObject *parent = nullptr); 19 | ~FileListModel() override; 20 | 21 | QVariant data(const QModelIndex &index, 22 | int role = Qt::DisplayRole) const override; 23 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 24 | bool setData(const QModelIndex &index, const QVariant &value, 25 | int role) override; 26 | Qt::ItemFlags flags(const QModelIndex &index) const override; 27 | 28 | void loadFileList(); 29 | void save(); 30 | int findFile(const QString &lastFileName); 31 | 32 | Q_SIGNALS: 33 | void changed(); 34 | 35 | private: 36 | QList> fileList_; 37 | }; 38 | 39 | } // namespace fcitx 40 | 41 | #endif // _PINYINDICTMANAGER_FILELISTMODEL_H_ 42 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/guicommon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2013-2020 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #ifndef GUICOMMON_H 9 | #define GUICOMMON_H 10 | 11 | #define DOWNLOAD_HOST_BASE "download.pinyin.sogou.com" 12 | #define HOST_BASE "pinyin.sogou.com" 13 | #define URL_BASE "http://" HOST_BASE "/dict/" 14 | 15 | #endif // GUICOMMON_H 16 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/log.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "log.h" 9 | 10 | namespace fcitx { 11 | 12 | Q_LOGGING_CATEGORY(dictmanager, "dictmanager") 13 | 14 | } // namespace fcitx 15 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_LOG_H_ 8 | #define _PINYINDICTMANAGER_LOG_H_ 9 | 10 | #include 11 | 12 | namespace fcitx { 13 | 14 | Q_DECLARE_LOGGING_CATEGORY(dictmanager) 15 | 16 | } // namespace fcitx 17 | 18 | #endif // _PINYINDICTMANAGER_LOG_H_ 19 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "main.h" 9 | #include "pinyindictmanager.h" 10 | #include 11 | 12 | namespace fcitx { 13 | 14 | PinyinDictManagerPlugin::PinyinDictManagerPlugin(QObject *parent) 15 | : FcitxQtConfigUIPlugin(parent) { 16 | registerDomain("fcitx5-chinese-addons", FCITX_INSTALL_LOCALEDIR); 17 | } 18 | 19 | FcitxQtConfigUIWidget *PinyinDictManagerPlugin::create(const QString &key) { 20 | Q_UNUSED(key); 21 | return new PinyinDictManager(nullptr); 22 | } 23 | 24 | } // namespace fcitx 25 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_MAIN_H_ 8 | #define _PINYINDICTMANAGER_MAIN_H_ 9 | 10 | #include "fcitxqtconfiguiplugin.h" 11 | 12 | namespace fcitx { 13 | 14 | class PinyinDictManagerPlugin : public FcitxQtConfigUIPlugin { 15 | Q_OBJECT 16 | public: 17 | Q_PLUGIN_METADATA(IID FcitxQtConfigUIFactoryInterface_iid FILE 18 | "pinyindictmanager.json") 19 | explicit PinyinDictManagerPlugin(QObject *parent = nullptr); 20 | FcitxQtConfigUIWidget *create(const QString &key) override; 21 | }; 22 | 23 | } // namespace fcitx 24 | 25 | #endif // _PINYINDICTMANAGER_MAIN_H_ 26 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/pinyindictmanager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_PINYINDICTMANAGER_H_ 8 | #define _PINYINDICTMANAGER_PINYINDICTMANAGER_H_ 9 | 10 | #include "filelistmodel.h" 11 | #include "pipeline.h" 12 | #include "ui_pinyindictmanager.h" 13 | #include 14 | 15 | namespace fcitx { 16 | 17 | class PinyinDictManager : public FcitxQtConfigUIWidget, 18 | public Ui::PinyinDictManager { 19 | Q_OBJECT 20 | public: 21 | PinyinDictManager(QWidget *parent); 22 | 23 | void load() override; 24 | void save() override; 25 | QString title() override; 26 | bool asyncSave() override; 27 | QString icon() override { return "fcitx-pinyin"; } 28 | 29 | private Q_SLOTS: 30 | void importFromFile(); 31 | void importFromSogou(); 32 | void importFromSogouOnline(); 33 | void removeDict(); 34 | void removeAllDict(); 35 | void clearUserDict(); 36 | void clearAllDict(); 37 | void openUserDirectory(); 38 | 39 | private: 40 | QString confirmImportFileName(const QString &defaultName); 41 | QString prepareDirectory(); 42 | QString prepareTempFile(const QString &tempFileTemplate); 43 | QString checkOverwriteFile(const QString &dirName, 44 | const QString &importName); 45 | void reload(); 46 | 47 | QAction *importFromFileAction_; 48 | QAction *importFromSogou_; 49 | QAction *importFromSogouOnline_; 50 | QAction *clearUserDictAction_; 51 | QAction *clearAllDataAction_; 52 | 53 | FileListModel *model_; 54 | 55 | Pipeline *pipeline_; 56 | }; 57 | 58 | } // namespace fcitx 59 | 60 | #endif // _PINYINDICTMANAGER_PINYINDICTMANAGER_H_ 61 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/pinyindictmanager.json: -------------------------------------------------------------------------------- 1 | { 2 | "addon": "pinyin", 3 | "files": ["dictmanager"] 4 | } 5 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/pinyindictmanager.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PinyinDictManager 4 | 5 | 6 | 7 | 0 8 | 0 9 | 494 10 | 356 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | &Import 23 | 24 | 25 | 26 | .. 27 | 28 | 29 | 30 | 31 | 32 | 33 | &Remove 34 | 35 | 36 | 37 | .. 38 | 39 | 40 | 41 | 42 | 43 | 44 | Remove &All 45 | 46 | 47 | 48 | .. 49 | 50 | 51 | 52 | 53 | 54 | 55 | &Clear Dictionary 56 | 57 | 58 | 59 | .. 60 | 61 | 62 | 63 | 64 | 65 | 66 | &Open User Data Directory 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Qt::Vertical 77 | 78 | 79 | 80 | 20 81 | 40 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/pipeline.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "pipeline.h" 8 | #include "pipelinejob.h" 9 | #include 10 | 11 | namespace fcitx { 12 | 13 | Pipeline::Pipeline(QObject *parent) : QObject(parent) {} 14 | 15 | void Pipeline::addJob(PipelineJob *job) { 16 | job->setParent(this); 17 | jobs_.push_back(job); 18 | connect(job, &PipelineJob::finished, this, [this](bool success) { 19 | if (success) { 20 | startNext(); 21 | } else { 22 | emitFinished(false); 23 | } 24 | }); 25 | } 26 | 27 | void Pipeline::abort() { 28 | if (index_ < 0) { 29 | return; 30 | } 31 | jobs_[index_]->abort(); 32 | index_ = -1; 33 | } 34 | 35 | void Pipeline::reset() { 36 | abort(); 37 | for (auto *job : jobs_) { 38 | delete job; 39 | } 40 | jobs_.clear(); 41 | } 42 | 43 | void Pipeline::start() { 44 | Q_ASSERT(!jobs_.isEmpty()); 45 | 46 | index_ = -1; 47 | startNext(); 48 | } 49 | 50 | void Pipeline::startNext() { 51 | if (index_ + 1 == jobs_.size()) { 52 | emitFinished(true); 53 | return; 54 | } 55 | index_ += 1; 56 | jobs_[index_]->start(); 57 | } 58 | 59 | void Pipeline::emitFinished(bool result) { 60 | for (auto *job : jobs_) { 61 | job->cleanUp(); 62 | } 63 | Q_EMIT finished(result); 64 | } 65 | 66 | } // namespace fcitx 67 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/pipeline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_PIPELINE_H_ 8 | #define _PINYINDICTMANAGER_PIPELINE_H_ 9 | 10 | #include "pipelinejob.h" 11 | #include 12 | #include 13 | 14 | namespace fcitx { 15 | 16 | class Pipeline : public QObject { 17 | Q_OBJECT 18 | public: 19 | Pipeline(QObject *parent = nullptr); 20 | 21 | void addJob(PipelineJob *job); 22 | void start(); 23 | void abort(); 24 | void reset(); 25 | 26 | Q_SIGNALS: 27 | void finished(bool); 28 | void messages(const QString &message); 29 | 30 | private: 31 | void startNext(); 32 | void emitFinished(bool); 33 | 34 | QVector jobs_; 35 | int index_ = -1; 36 | }; 37 | 38 | } // namespace fcitx 39 | 40 | #endif // _PINYINDICTMANAGER_PIPELINE_H_ 41 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/pipelinejob.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "pipelinejob.h" 8 | 9 | namespace fcitx { 10 | 11 | PipelineJob::PipelineJob(QObject *parent) : QObject(parent) {} 12 | 13 | } // namespace fcitx 14 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/pipelinejob.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_PIPELINEJOB_H_ 8 | #define _PINYINDICTMANAGER_PIPELINEJOB_H_ 9 | 10 | #include 11 | #include 12 | 13 | namespace fcitx { 14 | 15 | class PipelineJob : public QObject { 16 | Q_OBJECT 17 | public: 18 | PipelineJob(QObject *parent = nullptr); 19 | 20 | virtual void start() = 0; 21 | virtual void abort() = 0; 22 | virtual void cleanUp() = 0; 23 | 24 | Q_SIGNALS: 25 | void finished(bool success); 26 | void message(QMessageBox::Icon icon, const QString &message); 27 | }; 28 | 29 | } // namespace fcitx 30 | 31 | #endif // _PINYINDICTMANAGER_PIPELINEJOB_H_ 32 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/processrunner.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2013-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "processrunner.h" 8 | #include "guicommon.h" 9 | #include "log.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace fcitx { 17 | 18 | ProcessRunner::ProcessRunner(const QString &bin, const QStringList &args, 19 | const QString &file, QObject *parent) 20 | : PipelineJob(parent), bin_(bin), args_(args), file_(file) { 21 | connect(&process_, 22 | qOverload(&QProcess::finished), this, 23 | &ProcessRunner::processFinished); 24 | } 25 | 26 | void ProcessRunner::start() { 27 | if (process_.state() != QProcess::NotRunning) { 28 | process_.kill(); 29 | } 30 | 31 | qCDebug(dictmanager) << bin_ << args_; 32 | 33 | process_.start(bin_, args_); 34 | process_.closeReadChannel(QProcess::StandardError); 35 | process_.closeReadChannel(QProcess::StandardOutput); 36 | } 37 | 38 | void ProcessRunner::abort() { process_.kill(); } 39 | 40 | void ProcessRunner::cleanUp() { QFile::remove(file_); } 41 | 42 | void ProcessRunner::processFinished(int exitCode, QProcess::ExitStatus status) { 43 | if (status == QProcess::CrashExit) { 44 | Q_EMIT message(QMessageBox::Critical, _("Converter crashed.")); 45 | Q_EMIT finished(false); 46 | return; 47 | } 48 | 49 | if (exitCode != 0) { 50 | Q_EMIT message(QMessageBox::Warning, _("Convert failed.")); 51 | Q_EMIT finished(false); 52 | return; 53 | } 54 | 55 | Q_EMIT finished(true); 56 | } 57 | 58 | } // namespace fcitx 59 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/processrunner.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2013-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_PROCESSRUNNER_H_ 8 | #define _PINYINDICTMANAGER_PROCESSRUNNER_H_ 9 | 10 | #include "pipelinejob.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace fcitx { 17 | 18 | class ProcessRunner : public PipelineJob { 19 | Q_OBJECT 20 | public: 21 | explicit ProcessRunner(const QString &bin, const QStringList &args, 22 | const QString &file, QObject *parent = nullptr); 23 | void start() override; 24 | void abort() override; 25 | void cleanUp() override; 26 | 27 | private Q_SLOTS: 28 | void processFinished(int exitCode, QProcess::ExitStatus status); 29 | 30 | private: 31 | QProcess process_; 32 | QString bin_; 33 | QStringList args_; 34 | QString file_; 35 | }; 36 | 37 | } // namespace fcitx 38 | 39 | #endif // _PINYINDICTMANAGER_PROCESSRUNNER_H_ 40 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/renamefile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "renamefile.h" 8 | #include "guicommon.h" 9 | #include "log.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace fcitx { 17 | 18 | RenameFile::RenameFile(const QString &from, const QString &to, QObject *parent) 19 | : PipelineJob(parent), from_(from), to_(to) {} 20 | 21 | void RenameFile::start() { 22 | bool result = ::rename(from_.toLocal8Bit().constData(), 23 | to_.toLocal8Bit().constData()) >= 0; 24 | QMetaObject::invokeMethod(this, "emitFinished", Qt::QueuedConnection, 25 | Q_ARG(bool, result)); 26 | } 27 | 28 | void RenameFile::abort() {} 29 | 30 | void RenameFile::cleanUp() {} 31 | 32 | void RenameFile::emitFinished(bool result) { 33 | if (!result) { 34 | Q_EMIT message(QMessageBox::Critical, _("Converter crashed.")); 35 | return; 36 | } 37 | Q_EMIT finished(result); 38 | } 39 | 40 | } // namespace fcitx 41 | -------------------------------------------------------------------------------- /gui/pinyindictmanager/renamefile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018-2018 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINDICTMANAGER_RENAMEFILE_H_ 8 | #define _PINYINDICTMANAGER_RENAMEFILE_H_ 9 | 10 | #include "pipelinejob.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace fcitx { 19 | 20 | class RenameFile : public PipelineJob { 21 | Q_OBJECT 22 | public: 23 | explicit RenameFile(const QString &from, const QString &to, 24 | QObject *parent = nullptr); 25 | void start() override; 26 | void abort() override; 27 | void cleanUp() override; 28 | 29 | private Q_SLOTS: 30 | void emitFinished(bool result); 31 | 32 | private: 33 | QString from_, to_; 34 | }; 35 | 36 | } // namespace fcitx 37 | 38 | #endif // _PINYINDICTMANAGER_RENAMEFILE_H_ 39 | -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-cangjie.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-chn.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-chttrans-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-erbi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-pinyin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-punc-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-punc-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-remind-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-remind-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-shuangpin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-wbpy.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-wubi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/16x16/apps/fcitx-ziranma.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-cangjie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-chn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-erbi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-pinyin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-punc-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-remind-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-wbpy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-wubi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/16x16/apps/org.fcitx.Fcitx5.fcitx-ziranma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/16x16/apps/org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-cangjie.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-chn.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-chttrans-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-erbi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-pinyin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-punc-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-punc-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-remind-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-remind-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-shuangpin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-wbpy.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-wubi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/22x22/apps/fcitx-ziranma.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-cangjie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-chn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-erbi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-pinyin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-punc-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-remind-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-wbpy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-wubi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/22x22/apps/org.fcitx.Fcitx5.fcitx-ziranma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/22x22/apps/org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-cangjie.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-chn.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-chttrans-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-erbi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-pinyin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-punc-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-punc-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-remind-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-remind-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-shuangpin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-wbpy.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-wubi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/24x24/apps/fcitx-ziranma.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-cangjie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-chn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-erbi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-pinyin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-punc-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-remind-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-wbpy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-wubi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/24x24/apps/org.fcitx.Fcitx5.fcitx-ziranma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/24x24/apps/org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-cangjie.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-chn.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-chttrans-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-erbi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-pinyin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-punc-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-punc-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-remind-active.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-remind-inactive.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-shuangpin.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-wbpy.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-wubi.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/48x48/apps/fcitx-ziranma.png: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-cangjie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-cangjie.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-chn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-chn.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-chttrans-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-chttrans-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-erbi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-erbi.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-pinyin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-pinyin.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-punc-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-punc-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-punc-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-remind-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-remind-active.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-remind-inactive.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-shuangpin.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-wbpy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-wbpy.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-wubi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-wubi.png -------------------------------------------------------------------------------- /icon/48x48/apps/org.fcitx.Fcitx5.fcitx-ziranma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcitx/fcitx5-chinese-addons/3376f6dbd255eb5d907762989ae66e35dff2bc70/icon/48x48/apps/org.fcitx.Fcitx5.fcitx-ziranma.png -------------------------------------------------------------------------------- /icon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | foreach(size 16 22 24 48) 2 | install(DIRECTORY ${size}x${size} DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor 3 | PATTERN .* EXCLUDE 4 | PATTERN *~ EXCLUDE) 5 | endforeach(size 16 22 24 48) 6 | 7 | install(DIRECTORY scalable DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor 8 | PATTERN ".*" EXCLUDE 9 | PATTERN "*~" EXCLUDE) 10 | -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-fullwidth-active-symbolic.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-active-symbolic.svg -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-fullwidth-active.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-active.svg -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-fullwidth-inactive-symbolic.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-inactive-symbolic.svg -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-fullwidth-inactive.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-fullwidth-inactive.svg -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-punc-active-symbolic.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-active-symbolic.svg -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-punc-active.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-active.svg -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-punc-inactive-symbolic.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-inactive-symbolic.svg -------------------------------------------------------------------------------- /icon/scalable/apps/fcitx-punc-inactive.svg: -------------------------------------------------------------------------------- 1 | org.fcitx.Fcitx5.fcitx-punc-inactive.svg -------------------------------------------------------------------------------- /icon/scalable/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 49 | 51 | 60 | 65 | 70 | 75 | 76 | 77 | 82 | 83 | -------------------------------------------------------------------------------- /icon/scalable/apps/org.fcitx.Fcitx5.fcitx-fullwidth-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /icon/scalable/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 49 | 51 | 60 | 65 | 70 | 75 | 76 | 77 | 80 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /icon/scalable/apps/org.fcitx.Fcitx5.fcitx-fullwidth-inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 49 | 51 | 60 | 65 | 70 | 75 | 76 | 77 | 79 | 90 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /im/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(pinyin) 2 | add_subdirectory(table) 3 | -------------------------------------------------------------------------------- /im/pinyin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PINYIN_SOURCES 2 | pinyin.cpp 3 | customphrase.cpp 4 | symboldictionary.cpp 5 | workerthread.cpp 6 | pinyincandidate.cpp 7 | pinyinenginefactory.cpp 8 | ) 9 | 10 | add_fcitx5_addon(pinyin ${PINYIN_SOURCES}) 11 | target_link_libraries(pinyin Fcitx5::Core Fcitx5::Config LibIME::Pinyin Fcitx5::Module::Punctuation Fcitx5::Module::QuickPhrase Fcitx5::Module::Notifications Fcitx5::Module::Spell Fcitx5::Module::PinyinHelper Pthread::Pthread) 12 | 13 | if (TARGET Fcitx5::Module::LuaAddonLoader) 14 | target_compile_definitions(pinyin PRIVATE -DFCITX_HAS_LUA) 15 | target_link_libraries(pinyin Fcitx5::Module::LuaAddonLoader) 16 | install(FILES pinyin.lua DESTINATION "${FCITX_INSTALL_PKGDATADIR}/lua/imeapi/extensions" 17 | COMPONENT config) 18 | endif() 19 | 20 | install(TARGETS pinyin DESTINATION "${CMAKE_INSTALL_LIBDIR}/fcitx5") 21 | fcitx5_translate_desktop_file(pinyin.conf.in pinyin.conf) 22 | fcitx5_translate_desktop_file(shuangpin.conf.in shuangpin.conf) 23 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pinyin.conf" "${CMAKE_CURRENT_BINARY_DIR}/shuangpin.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/fcitx5/inputmethod" 24 | COMPONENT config) 25 | configure_file(pinyin-addon.conf.in.in pinyin-addon.conf.in) 26 | fcitx5_translate_desktop_file("${CMAKE_CURRENT_BINARY_DIR}/pinyin-addon.conf.in" pinyin-addon.conf) 27 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pinyin-addon.conf" RENAME pinyin.conf DESTINATION "${FCITX_INSTALL_PKGDATADIR}/addon" 28 | COMPONENT config) 29 | 30 | install(FILES "symbols" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/pinyin" COMPONENT config) 31 | 32 | if (ENABLE_DATA) 33 | 34 | add_custom_command( 35 | OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/chaizi.dict" 36 | DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/chaizi.txt" LibIME::pinyindict 37 | COMMAND LibIME::pinyindict "${CMAKE_CURRENT_SOURCE_DIR}/chaizi.txt" "${CMAKE_CURRENT_BINARY_DIR}/chaizi.dict") 38 | add_custom_target(chaizi-dict ALL DEPENDS "chaizi.dict") 39 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/chaizi.dict" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/pinyin") 40 | endif() 41 | -------------------------------------------------------------------------------- /im/pinyin/customphrase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023-2023 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYIN_CUSTOMPHRASE_H_ 8 | #define _PINYIN_CUSTOMPHRASE_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace fcitx { 23 | 24 | class CustomPhrase { 25 | public: 26 | explicit CustomPhrase(int order, std::string value) 27 | : order_(order), value_(std::move(value)) {} 28 | FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE_WITH_SPEC(CustomPhrase, 29 | noexcept) 30 | 31 | int order() const { return order_; } 32 | const std::string &value() const { return value_; } 33 | void setOrder(int order) { order_ = order; } 34 | std::string &mutableValue() { return value_; } 35 | 36 | bool isDynamic() const; 37 | 38 | std::string evaluate(const std::function 39 | &evaluator) const; 40 | 41 | static std::string builtinEvaluator(std::string_view key); 42 | 43 | private: 44 | int order_ = -1; 45 | std::string value_; 46 | }; 47 | 48 | class CustomPhraseDict { 49 | public: 50 | using TrieType = libime::DATrie; 51 | CustomPhraseDict(); 52 | 53 | void load(std::istream &in, bool loadDisabled = false); 54 | void save(std::ostream &out) const; 55 | void clear(); 56 | 57 | const std::vector *lookup(std::string_view key) const; 58 | 59 | void addPhrase(std::string_view key, std::string_view value, int order); 60 | void pinPhrase(std::string_view key, std::string_view value); 61 | void removePhrase(std::string_view key, std::string_view value); 62 | 63 | template 64 | void foreach(const T &callback) { 65 | std::string buf; 66 | index_.foreach([this, &buf, &callback](uint32_t index, size_t len, 67 | TrieType::position_type pos) { 68 | index_.suffix(buf, len, pos); 69 | callback(buf, data_[index]); 70 | return true; 71 | }); 72 | } 73 | 74 | private: 75 | std::vector *getOrCreateEntry(std::string_view key); 76 | TrieType index_; 77 | std::vector> data_; 78 | }; 79 | 80 | } // namespace fcitx 81 | 82 | #endif // _PINYIN_SYMBOLDICTIONARY_H_ 83 | -------------------------------------------------------------------------------- /im/pinyin/pinyin-addon.conf.in.in: -------------------------------------------------------------------------------- 1 | [Addon] 2 | Name=Pinyin 3 | Category=InputMethod 4 | Version=@PROJECT_VERSION@ 5 | Library=libpinyin 6 | Type=@FCITX_ADDON_TYPE@ 7 | OnDemand=True 8 | Configurable=True 9 | 10 | [Addon/Dependencies] 11 | 0=core:@REQUIRED_FCITX_VERSION@ 12 | 1=punctuation:@PROJECT_VERSION@ 13 | 14 | [Addon/OptionalDependencies] 15 | 0=fullwidth:@PROJECT_VERSION@ 16 | 1=quickphrase 17 | 2=cloudpinyin:@PROJECT_VERSION@ 18 | 3=notifications 19 | 4=spell 20 | 5=pinyinhelper:@PROJECT_VERSION@ 21 | 6=chttrans:@PROJECT_VERSION@ 22 | 7=imeapi 23 | -------------------------------------------------------------------------------- /im/pinyin/pinyin.conf.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Pinyin 3 | Icon=fcitx-pinyin 4 | Label=拼 5 | LangCode=zh_CN 6 | Addon=pinyin 7 | Configurable=True 8 | -------------------------------------------------------------------------------- /im/pinyin/pinyinenginefactory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "pinyinenginefactory.h" 9 | #include "pinyin.h" 10 | #include 11 | 12 | namespace fcitx { 13 | 14 | fcitx::AddonInstance * 15 | fcitx::PinyinEngineFactory::create(AddonManager *manager) { 16 | registerDomain("fcitx5-chinese-addons", FCITX_INSTALL_LOCALEDIR); 17 | return new PinyinEngine(manager->instance()); 18 | } 19 | 20 | } // namespace fcitx 21 | 22 | FCITX_ADDON_FACTORY_V2(pinyin, fcitx::PinyinEngineFactory) 23 | -------------------------------------------------------------------------------- /im/pinyin/pinyinenginefactory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYIN_PINYINENGINEFACTORY_H_ 8 | #define _PINYIN_PINYINENGINEFACTORY_H_ 9 | 10 | #include 11 | 12 | namespace fcitx { 13 | 14 | class PinyinEngineFactory : public AddonFactory { 15 | public: 16 | AddonInstance *create(AddonManager *manager) override; 17 | }; 18 | 19 | } // namespace fcitx 20 | 21 | #endif // _PINYIN_PINYINENGINEFACTORY_H_ -------------------------------------------------------------------------------- /im/pinyin/shuangpin.conf.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Shuangpin 3 | Icon=fcitx-shuangpin 4 | Label=双 5 | LangCode=zh_CN 6 | Addon=pinyin 7 | Configurable=True 8 | -------------------------------------------------------------------------------- /im/pinyin/symboldictionary.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023-2023 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "symboldictionary.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace fcitx { 18 | 19 | using ParseResult = std::tuple; 20 | 21 | std::optional findEnclosedQuote(std::string_view str) { 22 | enum class UnescapeState { NORMAL, ESCAPE }; 23 | auto state = UnescapeState::NORMAL; 24 | for (size_t i = 1; i < str.size(); i++) { 25 | switch (state) { 26 | case UnescapeState::NORMAL: 27 | if (str[i] == '\\') { 28 | state = UnescapeState::ESCAPE; 29 | } else if (str[i] == '\"') { 30 | return i; 31 | } 32 | break; 33 | case UnescapeState::ESCAPE: 34 | if (str[i] == '\\' || str[i] == 'n' || str[i] == '\"') { 35 | continue; 36 | } else { 37 | // Invalid escape. 38 | return std::nullopt; 39 | } 40 | state = UnescapeState::NORMAL; 41 | break; 42 | } 43 | } 44 | return std::nullopt; 45 | } 46 | 47 | std::optional parseSymbolLine(std::string_view line) { 48 | line = stringutils::trimView(line); 49 | if (line.empty()) { 50 | return std::nullopt; 51 | ; 52 | } 53 | std::string_view key; 54 | size_t valueStart = std::string_view::npos; 55 | if (line[0] == '\"') { 56 | auto quote = findEnclosedQuote(line); 57 | if (!quote.has_value()) { 58 | return std::nullopt; 59 | } 60 | auto end = *quote + 1; 61 | key = line.substr(0, end); 62 | valueStart = line.find_first_not_of(FCITX_WHITESPACE, end); 63 | if (valueStart == end) { 64 | return std::nullopt; 65 | } 66 | } else { 67 | auto end = line.find_first_of(FCITX_WHITESPACE); 68 | if (end == std::string_view::npos) { 69 | return std::nullopt; 70 | } 71 | key = line.substr(0, end); 72 | valueStart = line.find_first_not_of(FCITX_WHITESPACE, end); 73 | } 74 | if (valueStart == std::string_view::npos) { 75 | return std::nullopt; 76 | } 77 | std::string_view value = line.substr(valueStart); 78 | auto parsedKey = stringutils::unescapeForValue(key); 79 | if (!parsedKey) { 80 | return std::nullopt; 81 | } 82 | auto parsedValue = stringutils::unescapeForValue(value); 83 | if (!parsedValue) { 84 | return std::nullopt; 85 | } 86 | return std::make_tuple(std::move(*parsedKey), std::move(*parsedValue)); 87 | } 88 | 89 | SymbolDict::SymbolDict() = default; 90 | 91 | void SymbolDict::load(std::istream &in) { 92 | clear(); 93 | std::string line; 94 | 95 | while (std::getline(in, line)) { 96 | auto parseResult = parseSymbolLine(line); 97 | if (parseResult) { 98 | auto [key, value] = *parseResult; 99 | auto index = index_.exactMatchSearch(key); 100 | if (TrieType::isNoValue(index)) { 101 | if (data_.size() >= std::numeric_limits::max()) { 102 | break; 103 | } 104 | index = data_.size(); 105 | index_.set(key, index); 106 | data_.push_back({}); 107 | } 108 | data_[index].push_back(value); 109 | } 110 | } 111 | index_.shrink_tail(); 112 | data_.shrink_to_fit(); 113 | } 114 | 115 | const std::vector *SymbolDict::lookup(std::string_view key) const { 116 | auto index = index_.exactMatchSearch(key); 117 | if (TrieType::isNoValue(index)) { 118 | return nullptr; 119 | } 120 | 121 | return &data_[index]; 122 | } 123 | 124 | void SymbolDict::clear() { 125 | index_.clear(); 126 | data_.clear(); 127 | } 128 | 129 | } // namespace fcitx 130 | -------------------------------------------------------------------------------- /im/pinyin/symboldictionary.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #ifndef _PINYIN_SYMBOLDICTIONARY_H_ 9 | #define _PINYIN_SYMBOLDICTIONARY_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace fcitx { 19 | 20 | class SymbolDict { 21 | public: 22 | using TrieType = libime::DATrie; 23 | SymbolDict(); 24 | 25 | void load(std::istream &in); 26 | void clear(); 27 | 28 | const std::vector *lookup(std::string_view key) const; 29 | 30 | private: 31 | TrieType index_; 32 | std::vector> data_; 33 | }; 34 | 35 | } // namespace fcitx 36 | 37 | #endif // _PINYIN_SYMBOLDICTIONARY_H_ -------------------------------------------------------------------------------- /im/pinyin/workerthread.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "workerthread.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | WorkerThread::WorkerThread(fcitx::EventDispatcher &dispatcher) 15 | : dispatcher_(dispatcher), thread_(&WorkerThread::runThread, this) {} 16 | 17 | WorkerThread::~WorkerThread() { 18 | // Unlike other thread, there is no need to use a event loop since there is 19 | // no IO monitoring, simply use exit_ to notify the exit. 20 | { 21 | std::lock_guard lock(mutex_); 22 | exit_ = true; 23 | condition_.notify_one(); 24 | } 25 | if (thread_.joinable()) { 26 | thread_.join(); 27 | } 28 | } 29 | 30 | std::unique_ptr 31 | WorkerThread::addTaskImpl(std::function task, 32 | std::function onDone) { 33 | // Return an empty TrackableObject, so the unneeded task can be thrown away 34 | // by simply delete TaskToken. 35 | auto token = std::make_unique(); 36 | std::lock_guard lock(mutex_); 37 | queue_.push({.task = std::move(task), 38 | .callback = std::move(onDone), 39 | .context = token->watch()}); 40 | condition_.notify_one(); 41 | return token; 42 | } 43 | 44 | void WorkerThread::run() { 45 | while (true) { 46 | Task task; 47 | { 48 | std::unique_lock lock(mutex_); 49 | condition_.wait(lock, [this] { return exit_ || !queue_.empty(); }); 50 | if (exit_) { 51 | break; 52 | } 53 | 54 | task = std::move(queue_.front()); 55 | queue_.pop(); 56 | } 57 | // Run the actual task. 58 | task.task(); 59 | dispatcher_.scheduleWithContext(std::move(task.context), 60 | std::move(task.callback)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /im/pinyin/workerthread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYIN_WORKERTHREAD_H_ 8 | #define _PINYIN_WORKERTHREAD_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | class TaskToken : public fcitx::TrackableObject {}; 22 | 23 | class WorkerThread { 24 | public: 25 | WorkerThread(fcitx::EventDispatcher &dispatcher); 26 | ~WorkerThread(); 27 | 28 | template 29 | FCITX_NODISCARD std::unique_ptr 30 | addTask(std::packaged_task task, OnDone onDone) { 31 | // Wrap packaged_task and future in shared, since std::function require 32 | // copy-able. The reason that we wrap it with in the std::function is 33 | // because we need type erasure to store it. 34 | std::shared_future future = task.get_future(); 35 | std::function taskFunction = 36 | [task = std::make_shared( 37 | std::move(task))]() mutable { (*task)(); }; 38 | std::function callback = 39 | [onDone = std::move(onDone), future = std::move(future)]() mutable { 40 | onDone(future); 41 | }; 42 | 43 | return addTaskImpl(std::move(taskFunction), std::move(callback)); 44 | } 45 | 46 | private: 47 | std::unique_ptr addTaskImpl(std::function task, 48 | std::function onDone); 49 | static void runThread(WorkerThread *self) { self->run(); } 50 | void run(); 51 | 52 | struct Task { 53 | std::function task; 54 | std::function callback; 55 | fcitx::TrackableObjectReference context; 56 | }; 57 | 58 | fcitx::EventDispatcher &dispatcher_; 59 | std::mutex mutex_; 60 | std::queue> queue_; 61 | bool exit_ = false; 62 | std::condition_variable condition_; 63 | 64 | // Must be the last member, since we did not use a smart pointer to wrap it. 65 | // The thread will be started right away at the end of constructor. 66 | std::thread thread_; 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /im/table/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TABLE_SOURCES 2 | engine.cpp 3 | state.cpp 4 | ime.cpp 5 | context.cpp 6 | candidate.cpp 7 | factory.cpp 8 | ) 9 | add_fcitx5_addon(table ${TABLE_SOURCES}) 10 | target_link_libraries(table Fcitx5::Core Fcitx5::Config LibIME::Table LibIME::Pinyin Fcitx5::Module::Punctuation Fcitx5::Module::QuickPhrase Fcitx5::Module::PinyinHelper) 11 | target_compile_definitions(table PRIVATE FCITX_STRINGUTILS_ENABLE_BOOST_STRING_VIEW) 12 | install(TARGETS table DESTINATION "${CMAKE_INSTALL_LIBDIR}/fcitx5") 13 | configure_file(table.conf.in.in table.conf.in) 14 | fcitx5_translate_desktop_file("${CMAKE_CURRENT_BINARY_DIR}/table.conf.in" table.conf) 15 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/table.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/fcitx5/addon" 16 | COMPONENT config) 17 | 18 | file(GLOB TABLE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.conf.in.in) 19 | list(REMOVE_ITEM TABLE_FILES table.conf.in.in) 20 | foreach(TABLE_ORIG ${TABLE_FILES}) 21 | get_filename_component(TABLE_NAME "${TABLE_ORIG}" NAME_WE) 22 | configure_file(${TABLE_NAME}.conf.in.in "${CMAKE_CURRENT_BINARY_DIR}/${TABLE_NAME}.conf.in" @ONLY) 23 | fcitx5_translate_desktop_file("${CMAKE_CURRENT_BINARY_DIR}/${TABLE_NAME}.conf.in" ${TABLE_NAME}.conf) 24 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${TABLE_NAME}.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/fcitx5/inputmethod" 25 | COMPONENT config) 26 | endforeach() 27 | -------------------------------------------------------------------------------- /im/table/candidate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | 8 | #include "candidate.h" 9 | #include "engine.h" 10 | #include "state.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace fcitx { 24 | 25 | TableCandidateWord::TableCandidateWord(TableEngine *engine, Text text, 26 | size_t idx) 27 | : CandidateWord(std::move(text)), engine_(engine), idx_(idx) {} 28 | void TableCandidateWord::select(InputContext *inputContext) const { 29 | auto *state = inputContext->propertyFor(&engine_->factory()); 30 | // nullptr means use the last requested entry. 31 | auto *context = state->updateContext(nullptr); 32 | if (!context || idx_ >= context->candidates().size()) { 33 | return; 34 | } 35 | if (state->mode() == TableMode::ForgetWord) { 36 | state->forgetCandidateWord(idx_); 37 | return; 38 | } 39 | { 40 | const CommitAfterSelectWrapper commitAfterSelectRAII(state); 41 | context->select(idx_); 42 | } 43 | if (context->selected()) { 44 | state->commitBuffer(true); 45 | } 46 | state->updateUI(/*keepOldCursor=*/false, /*maybePredict=*/true); 47 | } 48 | TablePinyinCandidateWord::TablePinyinCandidateWord( 49 | TableEngine *engine, std::string word, 50 | const libime::TableBasedDictionary &dict, bool customHint) 51 | : engine_(engine), word_(std::move(word)) { 52 | setText(Text(word_)); 53 | if (utf8::lengthValidated(word_) == 1) { 54 | if (auto code = dict.reverseLookup(word_); !code.empty()) { 55 | Text comment; 56 | comment.append("~ "); 57 | if (customHint) { 58 | comment.append(dict.hint(code)); 59 | } else { 60 | comment.append(std::move(code)); 61 | } 62 | setComment(std::move(comment)); 63 | } 64 | } 65 | } 66 | void TablePinyinCandidateWord::select(InputContext *inputContext) const { 67 | auto *state = inputContext->propertyFor(&engine_->factory()); 68 | inputContext->commitString(word_); 69 | state->pushLastCommit("", word_); 70 | state->resetAndPredict(); 71 | } 72 | TablePunctuationCandidateWord::TablePunctuationCandidateWord(TableState *state, 73 | std::string word, 74 | bool isHalf) 75 | : state_(state), word_(std::move(word)) { 76 | setText(Text(word_)); 77 | if (isHalf) { 78 | setComment(Text(_("(Half)"))); 79 | } 80 | } 81 | void TablePunctuationCandidateWord::select(InputContext *inputContext) const { 82 | state_->commitBuffer(true); 83 | inputContext->commitString(word_); 84 | state_->reset(); 85 | } 86 | 87 | TablePredictCandidateWord::TablePredictCandidateWord(TableState *state, 88 | std::string word) 89 | : CandidateWord(Text(word)), state_(state), word_(std::move(word)) {} 90 | void TablePredictCandidateWord::select(InputContext *inputContext) const { 91 | state_->commitBuffer(true); 92 | inputContext->commitString(word_); 93 | state_->pushLastCommit("", word_); 94 | state_->resetAndPredict(); 95 | } 96 | 97 | TableActionableCandidateList::TableActionableCandidateList(TableState *state) 98 | : state_(state) {} 99 | 100 | bool TableActionableCandidateList::hasAction( 101 | const CandidateWord &candidate) const { 102 | return dynamic_cast(&candidate); 103 | } 104 | std::vector TableActionableCandidateList::candidateActions( 105 | const CandidateWord &candidate) const { 106 | if (!hasAction(candidate)) { 107 | return {}; 108 | } 109 | std::vector actions; 110 | CandidateAction action; 111 | action.setId(0); 112 | action.setText(_("Forget word")); 113 | actions.push_back(std::move(action)); 114 | return actions; 115 | } 116 | 117 | void TableActionableCandidateList::triggerAction(const CandidateWord &candidate, 118 | int id) { 119 | if (id != 0) { 120 | return; 121 | } 122 | if (const auto *tableCandidate = 123 | dynamic_cast(&candidate)) { 124 | state_->forgetCandidateWord(tableCandidate->idx_); 125 | } 126 | } 127 | } // namespace fcitx 128 | -------------------------------------------------------------------------------- /im/table/candidate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _TABLE_CANDIDATE_H_ 8 | #define _TABLE_CANDIDATE_H_ 9 | 10 | #include "engine.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace fcitx { 20 | 21 | class TableCandidateWord : public CandidateWord { 22 | public: 23 | TableCandidateWord(TableEngine *engine, Text text, size_t idx); 24 | 25 | void select(InputContext *inputContext) const override; 26 | 27 | TableEngine *engine_; 28 | size_t idx_; 29 | }; 30 | 31 | class TablePinyinCandidateWord : public CandidateWord { 32 | public: 33 | TablePinyinCandidateWord(TableEngine *engine, std::string word, 34 | const libime::TableBasedDictionary &dict, 35 | bool customHint); 36 | 37 | void select(InputContext *inputContext) const override; 38 | 39 | TableEngine *engine_; 40 | std::string word_; 41 | }; 42 | 43 | class TablePunctuationCandidateWord : public CandidateWord { 44 | public: 45 | TablePunctuationCandidateWord(TableState *state, std::string word, 46 | bool isHalf); 47 | 48 | void select(InputContext *inputContext) const override; 49 | 50 | const std::string &word() const { return word_; } 51 | 52 | private: 53 | TableState *state_; 54 | std::string word_; 55 | }; 56 | 57 | class TablePredictCandidateWord : public CandidateWord { 58 | public: 59 | TablePredictCandidateWord(TableState *state, std::string word); 60 | 61 | void select(InputContext *inputContext) const override; 62 | 63 | TableState *state_; 64 | std::string word_; 65 | }; 66 | 67 | class TableActionableCandidateList : public ActionableCandidateList { 68 | public: 69 | TableActionableCandidateList(TableState *state); 70 | 71 | bool hasAction(const CandidateWord &candidate) const override; 72 | std::vector 73 | candidateActions(const CandidateWord &candidate) const override; 74 | void triggerAction(const CandidateWord &candidate, int id) override; 75 | 76 | private: 77 | TableState *state_; 78 | }; 79 | 80 | } // namespace fcitx 81 | 82 | #endif // _TABLE_CANDIDATE_H_ 83 | -------------------------------------------------------------------------------- /im/table/cangjie.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Cangjie (Simplified Chinese) 3 | Icon=fcitx-cangjie 4 | Label=仓 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | Enable=False 9 | 10 | [Table] 11 | File=@LIBIME_INSTALL_PKGDATADIR@/cj.main.dict 12 | AutoSelect=True 13 | AutoSelectLength=-1 14 | NoMatchAutoSelectLength=0 15 | Hint=False 16 | MatchingKey=* 17 | OrderPolicy=No 18 | UseFullWidth=True 19 | QuickPhraseKey=semicolon 20 | 21 | [Table/PrevPage] 22 | 0=Up 23 | 1=minus 24 | 25 | [Table/NextPage] 26 | 0=Down 27 | 1=equal 28 | -------------------------------------------------------------------------------- /im/table/context.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "context.h" 8 | #include "ime.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace fcitx { 22 | 23 | TableContext::TableContext(libime::TableBasedDictionary &dict, 24 | const TableConfig &config, 25 | libime::UserLanguageModel &model) 26 | : libime::TableContext(dict, model), config_(config), 27 | prediction_(std::make_unique()) { 28 | prediction_->setUserLanguageModel(&model); 29 | } 30 | 31 | Text TableContext::preeditText(bool hint, bool clientPreedit) const { 32 | Text text; 33 | TextFormatFlag format = 34 | clientPreedit ? TextFormatFlag::Underline : TextFormatFlag::NoFlag; 35 | if (!*config_.commitAfterSelect) { 36 | for (size_t i = 0, e = selectedSize(); i < e; i++) { 37 | auto seg = selectedSegment(i); 38 | if (std::get(seg)) { 39 | text.append(std::get(seg), {format}); 40 | } else { 41 | auto segText = hint ? customHint(std::get(seg)) 42 | : std::get(seg); 43 | TextFormatFlags flags; 44 | if (*config_.commitInvalidSegment) { 45 | segText = stringutils::concat("(", segText, ")"); 46 | flags = format; 47 | } else { 48 | flags = {TextFormatFlag::DontCommit, TextFormatFlag::Strike, 49 | format}; 50 | } 51 | 52 | text.append(std::move(segText), flags); 53 | } 54 | } 55 | } 56 | 57 | std::string codeText; 58 | if (*config_.firstCandidateAsPreedit && !candidates().empty()) { 59 | codeText = candidates().front().toString(); 60 | } else { 61 | codeText = hint ? customHint(currentCode()) : currentCode(); 62 | } 63 | 64 | text.append(std::move(codeText), {format}); 65 | 66 | if (clientPreedit && *config_.preeditCursorPositionAtBeginning) { 67 | text.setCursor(0); 68 | } else { 69 | text.setCursor(text.textLength()); 70 | } 71 | return text; 72 | } 73 | } // namespace fcitx 74 | -------------------------------------------------------------------------------- /im/table/context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _TABLE_CONTEXT_H_ 8 | #define _TABLE_CONTEXT_H_ 9 | 10 | #include "ime.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace fcitx { 18 | 19 | class TableContext : public libime::TableContext { 20 | public: 21 | TableContext(libime::TableBasedDictionary &dict, const TableConfig &config, 22 | libime::UserLanguageModel &model); 23 | 24 | const TableConfig &config() { return config_; } 25 | std::string customHint(const std::string &code) const { 26 | if (*config_.displayCustomHint) { 27 | return dict().hint(code); 28 | } 29 | return code; 30 | } 31 | 32 | Text preeditText(bool hint, bool clientPreedit) const; 33 | 34 | libime::Prediction *prediction() const { 35 | if (!model().languageModelFile()) { 36 | return nullptr; 37 | } 38 | return prediction_.get(); 39 | } 40 | 41 | private: 42 | const TableConfig &config_; 43 | std::unique_ptr prediction_; 44 | }; 45 | } // namespace fcitx 46 | 47 | #endif // _TABLE_CONTEXT_H_ 48 | -------------------------------------------------------------------------------- /im/table/db.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Dianbaoma 3 | Icon=fcitx-dianbaoma 4 | Label=电 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | 9 | [Table] 10 | File=@LIBIME_INSTALL_PKGDATADIR@/db.main.dict 11 | AutoSelect=True 12 | AutoSelectLength=-1 13 | NoMatchAutoSelectLength=-1 14 | Hint=True 15 | OrderPolicy=Freq 16 | UseFullWidth=True 17 | QuickPhraseKey=semicolon 18 | QuickPhraseText=ABCDEFGHIJLKLMNOPQRSTUVWXYZ 19 | 20 | [Table/PrevPage] 21 | 0=Up 22 | 1=minus 23 | 24 | [Table/NextPage] 25 | 0=Down 26 | 1=equal 27 | 28 | [Table/Selection] 29 | 0=q 30 | 1=w 31 | 2=e 32 | 3=r 33 | 4=t 34 | 5=y 35 | 6=u 36 | 7=i 37 | 8=o 38 | 9=p 39 | -------------------------------------------------------------------------------- /im/table/erbi.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Erbi 3 | Icon=fcitx-erbi 4 | Label=二 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | 9 | [Table] 10 | File=@LIBIME_INSTALL_PKGDATADIR@/erbi.main.dict 11 | AutoSelect=True 12 | AutoSelectLength=-1 13 | AutoSelectRegex=[uv]. 14 | NoMatchAutoSelectLength=0 15 | Hint=False 16 | OrderPolicy=Freq 17 | UseFullWidth=True 18 | QuickPhraseKey=semicolon 19 | PinyinKey=[ 20 | MatchingKey=* 21 | AutoPhraseLength=4 22 | AutoPhraseWithPhrase=False 23 | SaveAutoPhraseAfter=-1 24 | UseContextRelatedOrder=False 25 | QuickPhraseText=ABCDEFGHIJLKLMNOPQRSTUVWXYZ 26 | 27 | [Table/PrevPage] 28 | 0=Up 29 | 1=minus 30 | 31 | [Table/NextPage] 32 | 0=Down 33 | 1=equal 34 | -------------------------------------------------------------------------------- /im/table/factory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "factory.h" 8 | #include "engine.h" 9 | #include 10 | 11 | namespace fcitx { 12 | 13 | fcitx::AddonInstance *fcitx::TableEngineFactory::create(AddonManager *manager) { 14 | registerDomain("fcitx5-chinese-addons", FCITX_INSTALL_LOCALEDIR); 15 | return new TableEngine(manager->instance()); 16 | } 17 | 18 | } // namespace fcitx 19 | 20 | FCITX_ADDON_FACTORY_V2(table, fcitx::TableEngineFactory) 21 | -------------------------------------------------------------------------------- /im/table/factory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024-2024 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _TABLE_FACTORY_H_ 8 | #define _TABLE_FACTORY_H_ 9 | 10 | #include 11 | namespace fcitx { 12 | 13 | class TableEngineFactory : public AddonFactory { 14 | public: 15 | AddonInstance *create(AddonManager *manager) override; 16 | }; 17 | 18 | } // namespace fcitx 19 | 20 | #endif // _TABLE_FACTORY_H_ -------------------------------------------------------------------------------- /im/table/qxm.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Bingchan 3 | Icon=fcitx-bingchan 4 | Label=冰 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | 9 | [Table] 10 | File=@LIBIME_INSTALL_PKGDATADIR@/qxm.main.dict 11 | AutoSelect=True 12 | AutoSelectLength=-1 13 | NoMatchAutoSelectLength=-1 14 | Hint=True 15 | MatchingKey=* 16 | OrderPolicy=Fast 17 | UseFullWidth=True 18 | QuickPhraseKey=semicolon 19 | AutoPhraseLength=4 20 | SaveAutoPhraseAfter=3 21 | QuickPhraseText=ABCDEFGHIJLKLMNOPQRSTUVWXYZ 22 | 23 | [Table/PrevPage] 24 | 0=Up 25 | 1=minus 26 | 27 | [Table/NextPage] 28 | 0=Down 29 | 1=equal 30 | -------------------------------------------------------------------------------- /im/table/state.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _TABLE_STATE_H_ 8 | #define _TABLE_STATE_H_ 9 | 10 | #include "context.h" 11 | #include "engine.h" 12 | #include "ime.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fcitx { 26 | 27 | enum class TableMode { 28 | Normal, 29 | ModifyDictionary, 30 | ForgetWord, 31 | Pinyin, 32 | LookupPinyin, 33 | Punctuation, 34 | }; 35 | 36 | struct EventSourceTime; 37 | 38 | class TableState : public InputContextProperty { 39 | public: 40 | TableState(InputContext *ic, TableEngine *engine) 41 | : ic_(ic), engine_(engine) {} 42 | 43 | InputContext *ic_; 44 | TableEngine *engine_; 45 | bool lastIsPunc_ = false; 46 | std::unique_ptr cancelLastEvent_; 47 | 48 | TableContext *updateContext(const InputMethodEntry *entry); 49 | void release(); 50 | void reset(const InputMethodEntry *entry = nullptr); 51 | void resetAndPredict(); 52 | void predict(); 53 | 54 | void keyEvent(const InputMethodEntry &entry, KeyEvent &event); 55 | 56 | void commitBuffer(bool commitCode, bool noRealCommit = false); 57 | void updateUI(bool keepOldCursor, bool maybePredict); 58 | void updatePuncCandidate(InputContext *inputContext, 59 | const std::string &original, 60 | const std::vector &candidates); 61 | void updatePuncPreedit(InputContext *inputContext); 62 | void pushLastCommit(const std::string &code, 63 | const std::string &lastSegment); 64 | 65 | void commitAfterSelect(int commitFrom); 66 | 67 | auto mode() const { return mode_; } 68 | 69 | void forgetCandidateWord(size_t idx); 70 | void handle2nd3rdCandidate(KeyEvent &event) { 71 | auto *context = context_.get(); 72 | if (!context) { 73 | return; 74 | } 75 | 76 | const auto &config = context->config(); 77 | handle2nd3rdCandidate(config, event); 78 | } 79 | 80 | auto context() const { return context_.get(); } 81 | 82 | private: 83 | bool handle2nd3rdCandidate(const TableConfig &config, KeyEvent &event); 84 | bool handlePuncCandidate(const TableConfig &config, KeyEvent &event); 85 | bool handleCandidateList(const TableConfig &config, KeyEvent &event); 86 | bool handleForgetWord(KeyEvent &event); 87 | bool handlePinyinMode(KeyEvent &event); 88 | bool handleLookupPinyinOrModifyDictionaryMode(KeyEvent &event); 89 | 90 | bool isContextEmpty() const; 91 | bool autoSelectCandidate() const; 92 | 93 | bool isComposeTableMode() const; 94 | 95 | std::unique_ptr 96 | predictCandidateList(const std::vector &words); 97 | std::string commitSegements(size_t from, size_t to); 98 | 99 | TableMode mode_ = TableMode::Normal; 100 | std::string pinyinModePrefix_; 101 | InputBuffer pinyinModeBuffer_{ 102 | {InputBufferOption::AsciiOnly, InputBufferOption::FixedCursor}}; 103 | size_t lookupPinyinIndex_ = 0; 104 | std::vector> lookupPinyinString_; 105 | std::string lastContext_; 106 | std::list> lastCommit_; 107 | std::string lastSegment_; 108 | std::list> autoPhraseBuffer_; 109 | std::unique_ptr context_; 110 | 111 | int keyReleased_ = -1; 112 | int keyReleasedIndex_ = -2; 113 | uint64_t lastKeyPressedTime_ = 0; 114 | }; 115 | 116 | class CommitAfterSelectWrapper { 117 | public: 118 | CommitAfterSelectWrapper(TableState *state) : state_(state) { 119 | if (auto *context = state->updateContext(nullptr)) { 120 | commitFrom_ = static_cast(context->selectedSize()); 121 | } 122 | } 123 | 124 | ~CommitAfterSelectWrapper() { 125 | if (commitFrom_ >= 0) { 126 | state_->commitAfterSelect(commitFrom_); 127 | } 128 | } 129 | 130 | private: 131 | TableState *state_; 132 | int commitFrom_ = -1; 133 | }; 134 | 135 | } // namespace fcitx 136 | 137 | #endif // _TABLE_STATE_H_ 138 | -------------------------------------------------------------------------------- /im/table/table.conf.in.in: -------------------------------------------------------------------------------- 1 | [Addon] 2 | Name=Table 3 | Category=InputMethod 4 | Library=libtable 5 | Type=@FCITX_ADDON_TYPE@ 6 | OnDemand=True 7 | Configurable=True 8 | Version=@PROJECT_VERSION@ 9 | 10 | [Addon/Dependencies] 11 | 0=core:@REQUIRED_FCITX_VERSION@ 12 | 1=punctuation:@PROJECT_VERSION@ 13 | 2=pinyinhelper:@PROJECT_VERSION@ 14 | 15 | [Addon/OptionalDependencies] 16 | 0=fullwidth:@PROJECT_VERSION@ 17 | 1=quickphrase 18 | 19 | -------------------------------------------------------------------------------- /im/table/wanfeng.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Wanfeng 3 | Icon=fcitx-wanfeng 4 | Label=晚 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | 9 | [Table] 10 | File=@LIBIME_INSTALL_PKGDATADIR@/wanfeng.main.dict 11 | AutoSelect=True 12 | AutoSelectLength=-1 13 | NoMatchAutoSelectLength=1 14 | Hint=True 15 | OrderPolicy=No 16 | UseFullWidth=True 17 | QuickPhraseKey=semicolon 18 | AutoPhraseLength=-1 19 | QuickPhraseText=ABCDEFGHIJLKLMNOPQRSTUVWXYZ 20 | 21 | [Table/PrevPage] 22 | 0=Up 23 | 1=minus 24 | 25 | [Table/NextPage] 26 | 0=Down 27 | 1=equal 28 | 29 | [Table/EndKey] 30 | 0=comma 31 | 1=semicolon 32 | 2=slash 33 | 3=period 34 | 35 | -------------------------------------------------------------------------------- /im/table/wbpy.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Wubi Pinyin 3 | Icon=fcitx-wubi 4 | Label=五 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | 9 | [Table] 10 | File=@LIBIME_INSTALL_PKGDATADIR@/wbpy.main.dict 11 | AutoSelect=True 12 | AutoSelectLength=-1 13 | NoMatchAutoSelectLength=-1 14 | NoSortInputLength=2 15 | Hint=True 16 | MatchingKey=z 17 | OrderPolicy=Freq 18 | UseFullWidth=True 19 | QuickPhraseKey=semicolon 20 | AutoPhraseLength=4 21 | SaveAutoPhraseAfter=3 22 | UseContextRelatedOrder=False 23 | QuickPhraseText=ABCDEFGHIJLKLMNOPQRSTUVWXYZ 24 | HintSeparator= 25 | 26 | [Table/PrevPage] 27 | 0=Up 28 | 1=minus 29 | 30 | [Table/NextPage] 31 | 0=Down 32 | 1=equal 33 | -------------------------------------------------------------------------------- /im/table/wbx.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Wubi 3 | Icon=fcitx-wubi 4 | Label=五 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | 9 | [Table] 10 | File=@LIBIME_INSTALL_PKGDATADIR@/wbx.main.dict 11 | AutoSelect=True 12 | AutoSelectLength=-1 13 | NoMatchAutoSelectLength=-1 14 | NoSortInputLength=2 15 | Hint=True 16 | MatchingKey=z 17 | PinyinKey=z 18 | OrderPolicy=Freq 19 | UseFullWidth=True 20 | QuickPhraseKey=semicolon 21 | AutoPhraseLength=4 22 | SaveAutoPhraseAfter=3 23 | UseContextRelatedOrder=False 24 | QuickPhraseText=ABCDEFGHIJLKLMNOPQRSTUVWXYZ 25 | HintSeparator= 26 | 27 | [Table/PrevPage] 28 | 0=Up 29 | 1=minus 30 | 31 | [Table/NextPage] 32 | 0=Down 33 | 1=equal 34 | -------------------------------------------------------------------------------- /im/table/zrm.conf.in.in: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=Ziranma 3 | Icon=fcitx-ziranma 4 | Label=自 5 | LangCode=zh_CN 6 | Addon=table 7 | Configurable=True 8 | 9 | [Table] 10 | File=@LIBIME_INSTALL_PKGDATADIR@/zrm.main.dict 11 | AutoSelect=True 12 | AutoSelectLength=-1 13 | NoMatchAutoSelectLength=-1 14 | Hint=True 15 | OrderPolicy=Fast 16 | UseFullWidth=True 17 | QuickPhraseKey=semicolon 18 | QuickPhraseText=ABCDEFGHIJLKLMNOPQRSTUVWXYZ 19 | 20 | [Table/PrevPage] 21 | 0=Up 22 | 1=minus 23 | 24 | [Table/NextPage] 25 | 0=Down 26 | 1=equal 27 | 28 | -------------------------------------------------------------------------------- /modules/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(chttrans) 2 | add_subdirectory(punctuation) 3 | add_subdirectory(fullwidth) 4 | add_subdirectory(cloudpinyin) 5 | add_subdirectory(pinyinhelper) 6 | -------------------------------------------------------------------------------- /modules/chttrans/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CHTTRANS_SOURCES 2 | chttrans.cpp chttrans-native.cpp 3 | ) 4 | if (ENABLE_OPENCC) 5 | set(CHTTRANS_SOURCES ${CHTTRANS_SOURCES} chttrans-opencc.cpp) 6 | endif() 7 | add_fcitx5_addon(chttrans ${CHTTRANS_SOURCES}) 8 | target_link_libraries(chttrans Fcitx5::Core Fcitx5::Config Fcitx5::Module::Notifications) 9 | if (ENABLE_OPENCC) 10 | target_link_libraries(chttrans OpenCC::OpenCC) 11 | if (TARGET Boost::json) 12 | target_link_libraries(chttrans Boost::json) 13 | endif() 14 | endif() 15 | install(TARGETS chttrans DESTINATION "${CMAKE_INSTALL_LIBDIR}/fcitx5") 16 | configure_file(chttrans.conf.in.in chttrans.conf.in) 17 | fcitx5_translate_desktop_file("${CMAKE_CURRENT_BINARY_DIR}/chttrans.conf.in" chttrans.conf) 18 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/chttrans.conf" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/addon" 19 | COMPONENT config) 20 | install(FILES gbks2t.tab DESTINATION "${CMAKE_INSTALL_DATADIR}/fcitx5/chttrans" COMPONENT config) 21 | -------------------------------------------------------------------------------- /modules/chttrans/chttrans-native.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "chttrans-native.h" 8 | #include "chttrans.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define TABLE_GBKS2T "chttrans/gbks2t.tab" 19 | 20 | using namespace fcitx; 21 | 22 | bool NativeBackend::loadOnce(const ChttransConfig & /*unused*/) { 23 | auto file = 24 | StandardPaths::global().open(StandardPathsType::PkgData, TABLE_GBKS2T); 25 | if (!file.isValid()) { 26 | return false; 27 | } 28 | 29 | IFDStreamBuf buffer(file.fd()); 30 | std::istream in(&buffer); 31 | 32 | std::string strBuf; 33 | while (std::getline(in, strBuf)) { 34 | // Get two char. 35 | auto simpStart = strBuf.begin(); 36 | uint32_t simp; 37 | uint32_t trad; 38 | 39 | auto tradStart = utf8::getNextChar(simpStart, strBuf.end(), &simp); 40 | auto end = utf8::getNextChar(tradStart, strBuf.end(), &trad); 41 | if (!utf8::isValidChar(simp) || !utf8::isValidChar(trad)) { 42 | continue; 43 | } 44 | std::string_view simpView(simpStart, tradStart); 45 | std::string_view tradView(tradStart, end); 46 | s2tMap_.try_emplace(std::string(simpView), tradView); 47 | t2sMap_.try_emplace(std::string(tradView), simpView); 48 | } 49 | return true; 50 | } 51 | 52 | std::string convert(const NativeBackend::MapType &transMap, 53 | const std::string &strHZ) { 54 | auto len = utf8::lengthValidated(strHZ); 55 | if (len == utf8::INVALID_LENGTH) { 56 | return strHZ; 57 | } 58 | auto range = fcitx::utf8::MakeUTF8StringViewRange(strHZ); 59 | std::string result; 60 | for (const auto &value : range) { 61 | auto iter = transMap.find(value); 62 | if (iter != transMap.end()) { 63 | result.append(iter->second); 64 | } else { 65 | result.append(value); 66 | } 67 | } 68 | 69 | return result; 70 | } 71 | 72 | std::string NativeBackend::convertSimpToTrad(const std::string &strHZ) { 73 | return convert(s2tMap_, strHZ); 74 | } 75 | 76 | std::string NativeBackend::convertTradToSimp(const std::string &strHZ) { 77 | return convert(t2sMap_, strHZ); 78 | } 79 | -------------------------------------------------------------------------------- /modules/chttrans/chttrans-native.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _CHTTRANS_CHTTRANS_NATIVE_H_ 8 | #define _CHTTRANS_CHTTRANS_NATIVE_H_ 9 | 10 | #include "chttrans.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class NativeBackend : public ChttransBackend { 17 | struct string_hash { 18 | using is_transparent = void; 19 | 20 | size_t operator()(const std::string_view str) const { 21 | constexpr std::hash hasher{}; 22 | return hasher(str); 23 | } 24 | }; 25 | 26 | public: 27 | using MapType = std::unordered_map>; 29 | std::string convertSimpToTrad(const std::string &) override; 30 | std::string convertTradToSimp(const std::string &) override; 31 | 32 | protected: 33 | bool loadOnce(const ChttransConfig &) override; 34 | 35 | private: 36 | MapType s2tMap_; 37 | MapType t2sMap_; 38 | }; 39 | 40 | #endif // _CHTTRANS_CHTTRANS_NATIVE_H_ 41 | -------------------------------------------------------------------------------- /modules/chttrans/chttrans-opencc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "chttrans-opencc.h" 8 | #include "chttrans.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace fcitx; 16 | 17 | bool OpenCCBackend::loadOnce(const ChttransConfig &config) { 18 | updateConfig(config); 19 | return true; 20 | } 21 | 22 | std::string OpenCCBackend::locateProfile(const std::string &profile) { 23 | auto profilePath = 24 | openCCStandardPath().locate(StandardPathsType::PkgData, profile); 25 | return profilePath.empty() ? profile : profilePath.string(); 26 | } 27 | 28 | void OpenCCBackend::updateConfig(const ChttransConfig &config) { 29 | auto s2tProfile = *config.openCCS2TProfile; 30 | if (s2tProfile.empty() || s2tProfile == "default") { 31 | const std::string preferredS2TProfile = "s2tw.json"; 32 | // Means it's resolved. 33 | if (locateProfile(preferredS2TProfile) != preferredS2TProfile) { 34 | s2tProfile = preferredS2TProfile; 35 | } else { 36 | s2tProfile = OPENCC_DEFAULT_CONFIG_SIMP_TO_TRAD; 37 | } 38 | } 39 | auto s2tProfilePath = locateProfile(s2tProfile); 40 | FCITX_DEBUG() << "s2tProfilePath: " << s2tProfilePath; 41 | 42 | try { 43 | auto s2t = std::make_unique(s2tProfilePath); 44 | s2t_ = std::move(s2t); 45 | } catch (const std::exception &e) { 46 | FCITX_WARN() << "exception when loading s2t profile: " << e.what(); 47 | } 48 | 49 | auto t2sProfile = *config.openCCT2SProfile; 50 | if (t2sProfile.empty() || t2sProfile == "default") { 51 | const std::string preferredT2SProfile = "tw2s.json"; 52 | // Means it's resolved. 53 | if (locateProfile(preferredT2SProfile) != preferredT2SProfile) { 54 | t2sProfile = preferredT2SProfile; 55 | } else { 56 | t2sProfile = OPENCC_DEFAULT_CONFIG_TRAD_TO_SIMP; 57 | } 58 | } 59 | auto t2sProfilePath = locateProfile(t2sProfile); 60 | FCITX_DEBUG() << "t2sProfilePath: " << t2sProfilePath; 61 | 62 | try { 63 | auto t2s = std::make_unique(t2sProfilePath); 64 | t2s_ = std::move(t2s); 65 | } catch (const std::exception &e) { 66 | FCITX_WARN() << "exception when loading t2s profile: " << e.what(); 67 | } 68 | } 69 | 70 | std::string OpenCCBackend::convertSimpToTrad(const std::string &str) { 71 | if (s2t_) { 72 | try { 73 | return s2t_->Convert(str); 74 | } catch (const std::exception &e) { 75 | } 76 | } 77 | return str; 78 | } 79 | 80 | std::string OpenCCBackend::convertTradToSimp(const std::string &str) { 81 | if (t2s_) { 82 | try { 83 | return t2s_->Convert(str); 84 | } catch (const std::exception &e) { 85 | } 86 | } 87 | return str; 88 | } 89 | -------------------------------------------------------------------------------- /modules/chttrans/chttrans-opencc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _CHTTRANS_CHTTRANS_OPENCC_H_ 8 | #define _CHTTRANS_CHTTRANS_OPENCC_H_ 9 | 10 | #include "chttrans.h" 11 | #include 12 | 13 | class OpenCCBackend : public ChttransBackend { 14 | public: 15 | std::string convertSimpToTrad(const std::string &) override; 16 | std::string convertTradToSimp(const std::string &) override; 17 | 18 | void updateConfig(const ChttransConfig &config) override; 19 | 20 | std::string locateProfile(const std::string &); 21 | 22 | protected: 23 | bool loadOnce(const ChttransConfig &config) override; 24 | 25 | private: 26 | std::unique_ptr s2t_; 27 | std::unique_ptr t2s_; 28 | }; 29 | 30 | #endif // _CHTTRANS_CHTTRANS_OPENCC_H_ 31 | -------------------------------------------------------------------------------- /modules/chttrans/chttrans.conf.in.in: -------------------------------------------------------------------------------- 1 | [Addon] 2 | Name=Simplified and Traditional Chinese Translation 3 | Category=Module 4 | Version=@PROJECT_VERSION@ 5 | Library=libchttrans 6 | Type=@FCITX_ADDON_TYPE@ 7 | Configurable=True 8 | OnDemand=True 9 | 10 | [Addon/Dependencies] 11 | 0=core:@REQUIRED_FCITX_VERSION@ 12 | 13 | [Addon/OptionalDependencies] 14 | 0=notifications 15 | -------------------------------------------------------------------------------- /modules/chttrans/opencc-profile-name.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace { 4 | [[maybe_unused]] constexpr std::string_view OpenCCProfileName[] = { 5 | NC_("OpenCC Profile", "Traditional Chinese (Taiwan standard) to Simplified Chinese"), 6 | NC_("OpenCC Profile", "Traditional Chinese (Taiwan standard) to Traditional Chinese"), 7 | NC_("OpenCC Profile", "Traditional Chinese (Taiwan standard) to Simplified Chinese (with phrases)"), 8 | NC_("OpenCC Profile", "Traditional Chinese to Traditional Chinese (Taiwan standard)"), 9 | NC_("OpenCC Profile", "Simplified Chinese to Traditional Chinese (Taiwan standard, with phrases)"), 10 | NC_("OpenCC Profile", "Simplified Chinese to Traditional Chinese (Taiwan standard)"), 11 | NC_("OpenCC Profile", "Simplified Chinese to Traditional Chinese"), 12 | NC_("OpenCC Profile", "Traditional Chinese (Hong Kong variant) to Simplified Chinese"), 13 | NC_("OpenCC Profile", "New Japanese Kanji (Shinjitai) to Traditional Chinese Characters (Kyūjitai)"), 14 | NC_("OpenCC Profile", "Traditional Chinese to Simplified Chinese"), 15 | NC_("OpenCC Profile", "Traditional Chinese Characters (Kyūjitai) to New Japanese Kanji (Shinjitai)"), 16 | NC_("OpenCC Profile", "Traditional Chinese (Hong Kong variant) to Traditional Chinese"), 17 | NC_("OpenCC Profile", "Traditional Chinese to Traditional Chinese (Hong Kong variant)"), 18 | NC_("OpenCC Profile", "Simplified Chinese to Traditional Chinese (Hong Kong variant)"), 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /modules/chttrans/update-opencc-profile-name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | OPENCC_PREFIX=`pkg-config --variable=prefix opencc` 4 | 5 | if [[ "$?" != 0 ]] || [[ -z OPENCC_PREFIX ]]; then 6 | echo "Cannot find opencc prefix" 7 | fi 8 | 9 | cat > opencc-profile-name.cpp < 11 | 12 | namespace { 13 | [[maybe_unused]] constexpr std::string_view OpenCCProfileName[] = { 14 | EOF 15 | 16 | for profile in `find "$OPENCC_PREFIX"/share/opencc -name "*.json"`; do 17 | PROFILE_NAME=`jq -r -e ".name" $profile` 18 | if [[ "$?" != 0 ]]; then 19 | continue 20 | fi 21 | echo " NC_(\"OpenCC Profile\", \"$PROFILE_NAME\")," >> opencc-profile-name.cpp 22 | done 23 | 24 | cat >> opencc-profile-name.cpp < 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _CLOUDPINYIN_CLOUDPINYIN_H_ 8 | #define _CLOUDPINYIN_CLOUDPINYIN_H_ 9 | 10 | #include "cloudpinyin_public.h" 11 | #include "fetch.h" 12 | #include "lrucache.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | FCITX_CONFIG_ENUM(CloudPinyinBackend, Google, GoogleCN, Baidu); 25 | FCITX_CONFIGURATION( 26 | CloudPinyinConfig, 27 | fcitx::Option toggleKey{ 28 | this, 29 | "Toggle Key", 30 | _("Toggle Key"), 31 | {fcitx::Key("Control+Alt+Shift+C")}}; 32 | fcitx::Option minimumLength{this, "MinimumPinyinLength", 33 | _("Minimum Pinyin Length"), 4}; 34 | fcitx::Option backend{this, "Backend", _("Backend"), 35 | CloudPinyinBackend::GoogleCN}; 36 | fcitx::OptionWithAnnotation proxy{ 37 | this, 38 | "Proxy", 39 | _("Proxy"), 40 | "", 41 | {}, 42 | {}, 43 | {_("The proxy format must be the one that is supported by cURL. " 44 | "Usually it is in the format of [scheme]://[host]:[port], e.g. " 45 | "http://localhost:1080.")}};); 46 | 47 | class Backend { 48 | public: 49 | FCITX_NODISCARD virtual bool prepareRequest(CurlQueue *queue, 50 | const std::string &pinyin) = 0; 51 | virtual std::string parseResult(CurlQueue *queue) = 0; 52 | virtual ~Backend() = default; 53 | }; 54 | 55 | class CloudPinyin : public fcitx::AddonInstance, 56 | public fcitx::TrackableObject { 57 | public: 58 | CloudPinyin(fcitx::AddonManager *manager); 59 | ~CloudPinyin() override; 60 | 61 | void reloadConfig() override; 62 | const fcitx::Configuration *getConfig() const override { return &config_; } 63 | void setConfig(const fcitx::RawConfig &config) override { 64 | config_.load(config, true); 65 | fcitx::safeSaveAsIni(config_, "conf/cloudpinyin.conf"); 66 | } 67 | 68 | void request(const std::string &pinyin, CloudPinyinCallback callback); 69 | const fcitx::KeyList &toggleKey() const { 70 | return config_.toggleKey.value(); 71 | } 72 | void resetError() { 73 | errorCount_ = 0; 74 | resetError_->setEnabled(false); 75 | } 76 | 77 | void notifyFinished(); 78 | 79 | private: 80 | FCITX_ADDON_EXPORT_FUNCTION(CloudPinyin, request); 81 | FCITX_ADDON_EXPORT_FUNCTION(CloudPinyin, toggleKey); 82 | FCITX_ADDON_EXPORT_FUNCTION(CloudPinyin, resetError); 83 | std::unique_ptr thread_; 84 | fcitx::EventLoop *eventLoop_; 85 | fcitx::EventDispatcher &dispatcher_; 86 | std::unique_ptr event_; 87 | std::unique_ptr resetError_; 88 | LRUCache cache_{2048}; 89 | std::unordered_map, 90 | fcitx::EnumHash> 91 | backends_; 92 | CloudPinyinConfig config_; 93 | int errorCount_ = 0; 94 | }; 95 | 96 | class CloudPinyinFactory : public fcitx::AddonFactory { 97 | public: 98 | fcitx::AddonInstance *create(fcitx::AddonManager *manager) override { 99 | return new CloudPinyin(manager); 100 | } 101 | }; 102 | 103 | #endif // _CLOUDPINYIN_CLOUDPINYIN_H_ 104 | -------------------------------------------------------------------------------- /modules/cloudpinyin/lrucache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _FCITX_LIBIME_LRU_H_ 8 | #define _FCITX_LIBIME_LRU_H_ 9 | 10 | #include 11 | #include 12 | 13 | template 14 | class LRUCache { 15 | using key_type = K; 16 | using value_type = V; 17 | using dict_type = 18 | std::unordered_map::iterator>>; 19 | 20 | public: 21 | LRUCache(size_t sz = 80) : sz_(sz) {} 22 | 23 | size_t size() const { return dict_.size(); } 24 | 25 | size_t capacity() const { return sz_; } 26 | 27 | bool empty() const { return dict_.empty(); } 28 | 29 | bool contains(const key_type &key) { 30 | return dict_.find(key) != dict_.end(); 31 | } 32 | 33 | template 34 | value_type *insert(const key_type &key, Args &&...args) { 35 | auto iter = dict_.find(key); 36 | if (iter == dict_.end()) { 37 | if (size() >= sz_) { 38 | evict(); 39 | } 40 | 41 | order_.push_front(key); 42 | auto r = dict_.emplace( 43 | key, std::make_pair(value_type(std::forward(args)...), 44 | order_.begin())); 45 | return &r.first->second.first; 46 | } 47 | return nullptr; 48 | } 49 | 50 | void erase(const key_type &key) { 51 | auto i = dict_.find(key); 52 | if (i == dict_.end()) { 53 | return; 54 | } 55 | order_.erase(i->second.second); 56 | dict_.erase(i); 57 | } 58 | 59 | value_type *find(const key_type &key) { 60 | // lookup value in the cache 61 | auto i = dict_.find(key); 62 | return find_helper(i); 63 | } 64 | 65 | void clear() { 66 | dict_.clear(); 67 | order_.clear(); 68 | } 69 | 70 | private: 71 | void evict() { 72 | // evict item from the end of most recently used list 73 | auto i = std::prev(order_.end()); 74 | dict_.erase(*i); 75 | order_.erase(i); 76 | } 77 | 78 | value_type *find_helper(typename dict_type::iterator i) { 79 | if (i == dict_.end()) { 80 | // value not in cache 81 | return nullptr; 82 | } 83 | 84 | // return the value, but first update its place in the most 85 | // recently used list 86 | auto j = i->second.second; 87 | if (j != order_.begin()) { 88 | order_.splice(order_.begin(), order_, j, std::next(j)); 89 | j = order_.begin(); 90 | i->second.second = j; 91 | } 92 | return &i->second.first; 93 | } 94 | dict_type dict_; 95 | std::list order_; 96 | size_t sz_; 97 | }; 98 | 99 | #endif // _FCITX_LIBIME_LRU_H_ 100 | -------------------------------------------------------------------------------- /modules/fullwidth/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(FULLWIDTH_SOURCES 2 | fullwidth.cpp 3 | ) 4 | add_fcitx5_addon(fullwidth ${FULLWIDTH_SOURCES}) 5 | target_link_libraries(fullwidth Fcitx5::Core Fcitx5::Config Fcitx5::Module::Notifications) 6 | install(TARGETS fullwidth DESTINATION "${CMAKE_INSTALL_LIBDIR}/fcitx5") 7 | configure_file(fullwidth.conf.in.in fullwidth.conf.in) 8 | fcitx5_translate_desktop_file("${CMAKE_CURRENT_BINARY_DIR}/fullwidth.conf.in" fullwidth.conf) 9 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/fullwidth.conf" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/addon" 10 | COMPONENT config) 11 | -------------------------------------------------------------------------------- /modules/fullwidth/fullwidth.conf.in.in: -------------------------------------------------------------------------------- 1 | [Addon] 2 | Name=Full width character 3 | Category=Module 4 | Version=@PROJECT_VERSION@ 5 | Library=libfullwidth 6 | Type=@FCITX_ADDON_TYPE@ 7 | OnDemand=True 8 | Configurable=True 9 | 10 | [Addon/Dependencies] 11 | 0=core:@REQUIRED_FCITX_VERSION@ 12 | 13 | [Addon/OptionalDependencies] 14 | 0=notifications 15 | -------------------------------------------------------------------------------- /modules/fullwidth/fullwidth.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _FULLWIDTH_FULLWIDTH_H_ 8 | #define _FULLWIDTH_FULLWIDTH_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | FCITX_CONFIGURATION(FullWidthConfig, fcitx::Option hotkey{ 19 | this, "Hotkey", _("Toggle key")};) 20 | 21 | class ToggleAction; 22 | 23 | class Fullwidth final : public fcitx::AddonInstance { 24 | class ToggleAction : public fcitx::Action { 25 | public: 26 | ToggleAction(Fullwidth *parent) : parent_(parent) {} 27 | 28 | std::string shortText(fcitx::InputContext *) const override { 29 | return parent_->enabled_ ? _("Full width Character") 30 | : _("Half width Character"); 31 | } 32 | std::string icon(fcitx::InputContext *) const override { 33 | return parent_->enabled_ ? "fcitx-fullwidth-active" 34 | : "fcitx-fullwidth-inactive"; 35 | } 36 | 37 | void activate(fcitx::InputContext *ic) override { 38 | return parent_->setEnabled(!parent_->enabled_, ic); 39 | } 40 | 41 | private: 42 | Fullwidth *parent_; 43 | }; 44 | 45 | public: 46 | Fullwidth(fcitx::Instance *instance); 47 | 48 | void reloadConfig() override; 49 | const fcitx::Configuration *getConfig() const override { return &config_; } 50 | void setConfig(const fcitx::RawConfig &config) override { 51 | config_.load(config, true); 52 | fcitx::safeSaveAsIni(config_, "conf/fullwidth.conf"); 53 | toggleAction_.setHotkey(config_.hotkey.value()); 54 | } 55 | 56 | FCITX_ADDON_DEPENDENCY_LOADER(notifications, instance_->addonManager()); 57 | 58 | bool inWhiteList(fcitx::InputContext *inputContext) const; 59 | 60 | void setEnabled(bool enabled, fcitx::InputContext *ic) { 61 | if (enabled != enabled_) { 62 | enabled_ = enabled; 63 | toggleAction_.update(ic); 64 | } 65 | } 66 | 67 | private: 68 | bool enabled_ = false; 69 | fcitx::Instance *instance_; 70 | FullWidthConfig config_; 71 | std::vector>> 72 | eventHandlers_; 73 | fcitx::ScopedConnection commitFilterConn_; 74 | std::unordered_set whiteList_; 75 | ToggleAction toggleAction_{this}; 76 | }; 77 | 78 | #endif // _FULLWIDTH_FULLWIDTH_H_ 79 | -------------------------------------------------------------------------------- /modules/pinyinhelper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PINYINHELPER_SOURCES 2 | pinyinhelper.cpp 3 | pinyinlookup.cpp 4 | stroke.cpp 5 | ) 6 | add_fcitx5_addon(pinyinhelper ${PINYINHELPER_SOURCES}) 7 | target_link_libraries(pinyinhelper 8 | Fcitx5::Core 9 | Fcitx5::Config 10 | LibIME::Core 11 | Fcitx5::Module::QuickPhrase 12 | Fcitx5::Module::Clipboard 13 | Pthread::Pthread) 14 | install(TARGETS pinyinhelper DESTINATION "${CMAKE_INSTALL_LIBDIR}/fcitx5") 15 | configure_file(pinyinhelper.conf.in.in pinyinhelper.conf.in) 16 | fcitx5_translate_desktop_file("${CMAKE_CURRENT_BINARY_DIR}/pinyinhelper.conf.in" pinyinhelper.conf) 17 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pinyinhelper.conf" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/addon" 18 | COMPONENT config) 19 | 20 | fcitx5_export_module(PinyinHelper TARGET pinyinhelper BUILD_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}" HEADERS pinyinhelper_public.h INSTALL) 21 | 22 | set(PY_STROKE_VER 20250329) 23 | set(PY_STROKE_TGT "${CMAKE_CURRENT_BINARY_DIR}/py_stroke.mb") 24 | set(PY_STROKE_TAR "py_stroke-${PY_STROKE_VER}.tar.gz") 25 | set(PY_STROKE_URL 26 | "http://download.fcitx-im.org/data/py_stroke-${PY_STROKE_VER}.tar.gz") 27 | fcitx5_download(py-stroke-download "${PY_STROKE_URL}" "${PY_STROKE_TAR}" 28 | c1a7ca7225d3614ab83353fc827503006a980447762018f53760425d7b5303a6) 29 | fcitx5_extract(py-stroke-extract "${PY_STROKE_TAR}" DEPENDS py-stroke-download 30 | OUTPUT ${PY_STROKE_TGT}) 31 | install(FILES "${PY_STROKE_TGT}" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/pinyinhelper") 32 | 33 | set(PY_TABLE_VER 20121124) 34 | set(PY_TABLE_TGT "${CMAKE_CURRENT_BINARY_DIR}/py_table.mb") 35 | set(PY_TABLE_TAR "py_table-${PY_TABLE_VER}.tar.gz") 36 | set(PY_TABLE_URL 37 | "http://download.fcitx-im.org/data/py_table-${PY_TABLE_VER}.tar.gz") 38 | fcitx5_download(py-table-download "${PY_TABLE_URL}" "${PY_TABLE_TAR}" 39 | 42146ac97de6c13d55f9e99ed873915f4c66739e9c11532a34556badf9792c04) 40 | fcitx5_extract(py-table-extract "${PY_TABLE_TAR}" DEPENDS py-table-download 41 | OUTPUT ${PY_TABLE_TGT}) 42 | install(FILES "${PY_TABLE_TGT}" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/pinyinhelper") 43 | -------------------------------------------------------------------------------- /modules/pinyinhelper/pinyinhelper.conf.in.in: -------------------------------------------------------------------------------- 1 | [Addon] 2 | Name=Extra Pinyin functionality 3 | Category=Module 4 | Version=@PROJECT_VERSION@ 5 | Library=libpinyinhelper 6 | Type=@FCITX_ADDON_TYPE@ 7 | OnDemand=False 8 | 9 | [Addon/Dependencies] 10 | 0=core:@REQUIRED_FCITX_VERSION@ 11 | 12 | [Addon/OptionalDependencies] 13 | 0=quickphrase 14 | 1=clipboard 15 | -------------------------------------------------------------------------------- /modules/pinyinhelper/pinyinhelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINHELPER_PINYINHELPER_H_ 8 | #define _PINYINHELPER_PINYINHELPER_H_ 9 | 10 | #include "pinyinhelper_public.h" 11 | #include "pinyinlookup.h" 12 | #include "stroke.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace fcitx { 22 | 23 | class PinyinHelper final : public AddonInstance { 24 | public: 25 | PinyinHelper(Instance *instance); 26 | 27 | std::vector lookup(uint32_t); 28 | std::vector> fullLookup(uint32_t); 29 | std::vector> 30 | lookupStroke(const std::string &input, int limit); 31 | std::string reverseLookupStroke(const std::string &input); 32 | std::string prettyStrokeString(const std::string &input); 33 | void loadStroke(); 34 | 35 | FCITX_ADDON_EXPORT_FUNCTION(PinyinHelper, lookup); 36 | FCITX_ADDON_EXPORT_FUNCTION(PinyinHelper, fullLookup); 37 | FCITX_ADDON_EXPORT_FUNCTION(PinyinHelper, lookupStroke); 38 | FCITX_ADDON_EXPORT_FUNCTION(PinyinHelper, loadStroke); 39 | FCITX_ADDON_EXPORT_FUNCTION(PinyinHelper, reverseLookupStroke); 40 | FCITX_ADDON_EXPORT_FUNCTION(PinyinHelper, prettyStrokeString); 41 | 42 | FCITX_ADDON_DEPENDENCY_LOADER(quickphrase, instance_->addonManager()); 43 | FCITX_ADDON_DEPENDENCY_LOADER(clipboard, instance_->addonManager()); 44 | 45 | private: 46 | void initQuickPhrase(); 47 | Instance *instance_; 48 | PinyinLookup lookup_; 49 | Stroke stroke_; 50 | std::unique_ptr deferEvent_; 51 | std::unique_ptr> handler_; 52 | }; 53 | } // namespace fcitx 54 | 55 | #endif // _PINYINHELPER_PINYINHELPER_H_ 56 | -------------------------------------------------------------------------------- /modules/pinyinhelper/pinyinhelper_public.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINHELPER_PINYINHELPER_PUBLIC_H_ 8 | #define _PINYINHELPER_PINYINHELPER_PUBLIC_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | FCITX_ADDON_DECLARE_FUNCTION(PinyinHelper, lookup, 15 | std::vector(uint32_t)); 16 | /* return with fullpinyin (in form of ü), pinyin with tone, and tone */ 17 | FCITX_ADDON_DECLARE_FUNCTION( 18 | PinyinHelper, fullLookup, 19 | std::vector>(uint32_t)); 20 | FCITX_ADDON_DECLARE_FUNCTION(PinyinHelper, lookupStroke, 21 | std::vector>( 22 | const std::string &, int limit)); 23 | FCITX_ADDON_DECLARE_FUNCTION(PinyinHelper, reverseLookupStroke, 24 | std::string(const std::string &)); 25 | FCITX_ADDON_DECLARE_FUNCTION(PinyinHelper, prettyStrokeString, 26 | std::string(const std::string &)); 27 | FCITX_ADDON_DECLARE_FUNCTION(PinyinHelper, loadStroke, void()); 28 | 29 | #endif // _PINYINHELPER_PINYINHELPER_PUBLIC_H_ 30 | -------------------------------------------------------------------------------- /modules/pinyinhelper/pinyinlookup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINHELPER_PINYINLOOKUP_H_ 8 | #define _PINYINHELPER_PINYINLOOKUP_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace fcitx { 17 | 18 | struct PinyinLookupData { 19 | uint8_t consonant; 20 | uint8_t vocal; 21 | uint8_t tone; 22 | }; 23 | 24 | class PinyinLookup { 25 | public: 26 | bool load(); 27 | std::vector lookup(uint32_t hz); 28 | std::vector> 29 | fullLookup(uint32_t hz); 30 | 31 | private: 32 | std::unordered_map> data_; 33 | bool loaded_ = false; 34 | bool loadResult_ = false; 35 | }; 36 | } // namespace fcitx 37 | 38 | #endif // _PINYINHELPER_PINYINLOOKUP_H_ 39 | -------------------------------------------------------------------------------- /modules/pinyinhelper/stroke.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PINYINHELPER_STROKE_H_ 8 | #define _PINYINHELPER_STROKE_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace fcitx { 18 | 19 | class Stroke { 20 | public: 21 | Stroke(); 22 | 23 | void loadAsync(); 24 | bool load(); 25 | std::vector> 26 | lookup(std::string_view input, int limit); 27 | std::string prettyString(const std::string &input) const; 28 | std::string reverseLookup(const std::string &hanzi) const; 29 | 30 | private: 31 | libime::DATrie dict_; 32 | libime::DATrie revserseDict_; 33 | bool loaded_ = false; 34 | bool loadResult_ = false; 35 | 36 | std::future, libime::DATrie>> 37 | loadFuture_; 38 | }; 39 | } // namespace fcitx 40 | 41 | #endif // _PINYINHELPER_STROKE_H_ 42 | -------------------------------------------------------------------------------- /modules/punctuation/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PUNCTUATION_SOURCES 2 | punctuation.cpp 3 | ) 4 | 5 | set(PUNCTUATION_DATA_FILES 6 | punc.mb.zh_CN 7 | punc.mb.zh_HK 8 | punc.mb.zh_TW 9 | ) 10 | 11 | add_fcitx5_addon(punctuation ${PUNCTUATION_SOURCES}) 12 | target_link_libraries(punctuation Fcitx5::Core Fcitx5::Config Fcitx5::Module::Notifications) 13 | install(TARGETS punctuation DESTINATION "${CMAKE_INSTALL_LIBDIR}/fcitx5") 14 | configure_file(punctuation.conf.in.in punctuation.conf.in) 15 | fcitx5_translate_desktop_file("${CMAKE_CURRENT_BINARY_DIR}/punctuation.conf.in" punctuation.conf) 16 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/punctuation.conf" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/addon" 17 | COMPONENT config) 18 | install(FILES ${PUNCTUATION_DATA_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/fcitx5/punctuation" 19 | COMPONENT config) 20 | 21 | fcitx5_export_module(Punctuation TARGET punctuation BUILD_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}" HEADERS punctuation_public.h INSTALL) 22 | -------------------------------------------------------------------------------- /modules/punctuation/punc.mb.zh_CN: -------------------------------------------------------------------------------- 1 | . 。 2 | , , 3 | ? ? 4 | " “ ” 5 | : : 6 | ; ; 7 | ' ‘ ’ 8 | < 《 9 | > 》 10 | \ 、 11 | ! ! 12 | # # 13 | # # 14 | $ $ 15 | $ ¥ 16 | $ $ 17 | % % 18 | % % 19 | ^ …… 20 | _ —— 21 | ( ( 22 | ) ) 23 | [ 【 24 | [ 「 25 | [ 『 26 | [ ❲ 27 | [ [ 28 | [ [ 29 | ] 】 30 | ] 」 31 | ] 』 32 | ] ❳ 33 | ] ] 34 | ] ] 35 | { { 36 | { { 37 | } } 38 | } } 39 | ~ ~ 40 | ` ` 41 | ` · 42 | -------------------------------------------------------------------------------- /modules/punctuation/punc.mb.zh_HK: -------------------------------------------------------------------------------- 1 | . 。 2 | , , 3 | ? ? 4 | " “ ” 5 | : : 6 | ; ; 7 | ' ‘ ’ 8 | < 《 9 | > 》 10 | \ 、 11 | ! ! 12 | $ $ 13 | ^ …… 14 | _ —— 15 | ( ( 16 | ) ) 17 | [ · 18 | ] 「 」 19 | ~ ~ 20 | -------------------------------------------------------------------------------- /modules/punctuation/punc.mb.zh_TW: -------------------------------------------------------------------------------- 1 | . 。 2 | , , 3 | ? ? 4 | : : 5 | ; ; 6 | < 《 》 7 | > 〈 〉 8 | \ 、 9 | ! ! 10 | $ $ 11 | ^ …… 12 | * × 13 | _ —— 14 | ( ( 15 | ) ) 16 | [ 「 17 | ] 」 18 | { 『 19 | } 』 20 | ~ ~ 21 | -------------------------------------------------------------------------------- /modules/punctuation/punctuation.conf.in.in: -------------------------------------------------------------------------------- 1 | [Addon] 2 | Name=Punctuation 3 | Category=Module 4 | Version=@PROJECT_VERSION@ 5 | Library=libpunctuation 6 | Type=@FCITX_ADDON_TYPE@ 7 | OnDemand=True 8 | Configurable=True 9 | 10 | [Addon/Dependencies] 11 | 0=core:@REQUIRED_FCITX_VERSION@ 12 | 13 | [Addon/OptionalDependencies] 14 | 0=notifications 15 | -------------------------------------------------------------------------------- /modules/punctuation/punctuation_public.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #ifndef _PUNCTUATION_PUNCTUATION_PUBLIC_H_ 8 | #define _PUNCTUATION_PUNCTUATION_PUBLIC_H_ 9 | 10 | #include 11 | namespace fcitx { 12 | class InputContext; 13 | } 14 | 15 | FCITX_ADDON_DECLARE_FUNCTION( 16 | Punctuation, getPunctuation, 17 | const std::pair &(const std::string &language, 18 | uint32_t unicode)); 19 | FCITX_ADDON_DECLARE_FUNCTION(Punctuation, cancelLast, 20 | const std::string &(const std::string &language, 21 | InputContext *ic)); 22 | FCITX_ADDON_DECLARE_FUNCTION(Punctuation, pushPunctuation, 23 | const std::string &(const std::string &language, 24 | InputContext *ic, 25 | uint32_t unicode)); 26 | FCITX_ADDON_DECLARE_FUNCTION( 27 | Punctuation, pushPunctuationV2, 28 | std::pair(const std::string &language, 29 | InputContext *ic, uint32_t unicode)); 30 | 31 | FCITX_ADDON_DECLARE_FUNCTION( 32 | Punctuation, getPunctuationCandidates, 33 | std::vector(const std::string &language, uint32_t unicode)); 34 | 35 | #endif // _PUNCTUATION_PUNCTUATION_PUBLIC_H_ 36 | -------------------------------------------------------------------------------- /org.fcitx.Fcitx5.Addon.ChineseAddons.metainfo.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.fcitx.Fcitx5.Addon.ChineseAddons 4 | org.fcitx.Fcitx5 5 | CC0-1.0 6 | GPL-2.0+ and LGPL-2.1+ 7 | Chinese Addons 8 | Add support for Pinyin, Table and many other Chinese related functionality to Fcitx 9 | 10 | The Fcitx Team 11 | 12 | https://fcitx-im.org 13 | https://github.com/fcitx/fcitx5-chinese-addons/issues 14 | https://github.com/fcitx/fcitx5-chinese-addons 15 | Fcitx 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /po/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | fcitx5_install_translation(fcitx5-chinese-addons) 2 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | 2 | ca 3 | da 4 | de 5 | he 6 | ja 7 | ko 8 | ru 9 | vi 10 | zh_CN 11 | zh_TW 12 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | configure_file(testdir.h.in ${CMAKE_CURRENT_BINARY_DIR}/testdir.h @ONLY) 2 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 3 | 4 | add_executable(testpunctuation testpunctuation.cpp) 5 | target_link_libraries(testpunctuation Fcitx5::Core Fcitx5::Module::Punctuation) 6 | add_dependencies(testpunctuation punctuation punctuation.conf.in-fmt) 7 | add_test(NAME testpunctuation COMMAND testpunctuation) 8 | 9 | if (ENABLE_CLOUDPINYIN) 10 | add_executable(testcloudpinyin testcloudpinyin.cpp) 11 | target_link_libraries(testcloudpinyin Fcitx5::Core Fcitx5::Module::CloudPinyin) 12 | add_dependencies(testcloudpinyin cloudpinyin copy-addon-cloudpinyin) 13 | endif() 14 | 15 | add_executable(testpinyinhelper testpinyinhelper.cpp) 16 | target_link_libraries(testpinyinhelper Fcitx5::Core Fcitx5::Module::PinyinHelper) 17 | add_dependencies(testpinyinhelper pinyin pinyin.conf.in-fmt pinyinhelper pinyinhelper.conf.in-fmt) 18 | add_test(NAME testpinyinhelper COMMAND testpinyinhelper) 19 | 20 | add_executable(testfullwidth testfullwidth.cpp) 21 | target_link_libraries(testfullwidth Fcitx5::Core Fcitx5::Module::TestFrontend Fcitx5::Module::TestIM) 22 | add_dependencies(testfullwidth fullwidth fullwidth.conf.in-fmt) 23 | add_test(NAME testfullwidth COMMAND testfullwidth) 24 | 25 | add_subdirectory(inputmethod) 26 | add_executable(testchttrans testchttrans.cpp) 27 | target_link_libraries(testchttrans Fcitx5::Core Fcitx5::Module::TestFrontend Fcitx5::Module::TestIM) 28 | add_dependencies(testchttrans chttrans chttrans.conf.in-fmt copy-addon copy-testim) 29 | add_test(NAME testchttrans COMMAND testchttrans) 30 | 31 | add_subdirectory(addon) 32 | add_executable(testpinyin testpinyin.cpp) 33 | target_link_libraries(testpinyin Fcitx5::Core Fcitx5::Module::TestFrontend) 34 | add_dependencies(testpinyin pinyin pinyinhelper copy-addon copy-im) 35 | add_test(NAME testpinyin COMMAND testpinyin) 36 | add_executable(testtable testtable.cpp) 37 | target_link_libraries(testtable Fcitx5::Core Fcitx5::Module::TestFrontend) 38 | add_dependencies(testtable table copy-addon copy-im) 39 | add_test(NAME testtable COMMAND testtable) 40 | 41 | add_executable(testcustomphrase testcustomphrase.cpp ../im/pinyin/customphrase.cpp) 42 | target_compile_definitions(testcustomphrase PRIVATE "-DFCITX_CUSTOM_PHRASE_TEST") 43 | target_link_libraries(testcustomphrase Fcitx5::Utils LibIME::Core) 44 | add_test(NAME testcustomphrase COMMAND testcustomphrase) 45 | 46 | add_executable(testsymboldictionary testsymboldictionary.cpp ../im/pinyin/symboldictionary.cpp) 47 | target_link_libraries(testsymboldictionary Fcitx5::Utils LibIME::Core) 48 | add_test(NAME testsymboldictionary COMMAND testsymboldictionary) 49 | -------------------------------------------------------------------------------- /test/addon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_target(copy-addon DEPENDS 2 | pinyin-addon.conf.in-fmt 3 | table.conf.in-fmt 4 | pinyinhelper.conf.in-fmt 5 | punctuation.conf.in-fmt 6 | fullwidth.conf.in-fmt 7 | chttrans.conf.in-fmt 8 | cloudpinyin.conf.in-fmt 9 | ) 10 | add_custom_command(TARGET copy-addon COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/im/pinyin/pinyin-addon.conf ${CMAKE_CURRENT_BINARY_DIR}/pinyin.conf) 11 | add_custom_command(TARGET copy-addon COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/im/table/table.conf ${CMAKE_CURRENT_BINARY_DIR}/table.conf) 12 | add_custom_command(TARGET copy-addon COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/modules/punctuation/punctuation.conf ${CMAKE_CURRENT_BINARY_DIR}/punctuation.conf) 13 | add_custom_command(TARGET copy-addon COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/modules/pinyinhelper/pinyinhelper.conf ${CMAKE_CURRENT_BINARY_DIR}/pinyinhelper.conf) 14 | add_custom_command(TARGET copy-addon COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/modules/fullwidth/fullwidth.conf ${CMAKE_CURRENT_BINARY_DIR}/fullwidth.conf) 15 | add_custom_command(TARGET copy-addon COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/modules/chttrans/chttrans.conf ${CMAKE_CURRENT_BINARY_DIR}/chttrans.conf) 16 | 17 | if (ENABLE_CLOUDPINYIN) 18 | add_custom_target(copy-addon-cloudpinyin DEPENDS cloudpinyin.conf.in-fmt) 19 | add_custom_command(TARGET copy-addon-cloudpinyin COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/modules/cloudpinyin/cloudpinyin.conf ${CMAKE_CURRENT_BINARY_DIR}/cloudpinyin.conf) 20 | endif() 21 | -------------------------------------------------------------------------------- /test/inputmethod/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_target(copy-im DEPENDS pinyin.conf.in-fmt erbi.conf.in-fmt wbx.conf.in-fmt) 2 | add_custom_command(TARGET copy-im COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/im/pinyin/pinyin.conf ${CMAKE_CURRENT_BINARY_DIR}/pinyin.conf) 3 | add_custom_command(TARGET copy-im COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/im/table/erbi.conf ${CMAKE_CURRENT_BINARY_DIR}/erbi.conf) 4 | add_custom_command(TARGET copy-im COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/im/table/wbx.conf ${CMAKE_CURRENT_BINARY_DIR}/wbx.conf) 5 | 6 | add_custom_target(copy-testim DEPENDS pinyin.conf.in-fmt) 7 | add_custom_command(TARGET copy-testim COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/test/inputmethod/sim.conf ${PROJECT_BINARY_DIR}/test/inputmethod/sim.conf) 8 | add_custom_command(TARGET copy-testim COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/test/inputmethod/trad.conf ${PROJECT_BINARY_DIR}/test/inputmethod/trad.conf) 9 | -------------------------------------------------------------------------------- /test/inputmethod/sim.conf: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=sim 3 | LangCode=zh_CN 4 | Addon=testim 5 | 6 | -------------------------------------------------------------------------------- /test/inputmethod/trad.conf: -------------------------------------------------------------------------------- 1 | [InputMethod] 2 | Name=trad 3 | LangCode=zh_TW 4 | Addon=testim 5 | -------------------------------------------------------------------------------- /test/testcloudpinyin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "cloudpinyin_public.h" 8 | #include "testdir.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | int main() { 19 | fcitx::setupTestingEnvironment(TESTING_BINARY_DIR, {"bin"}, 20 | {"test", TESTING_SOURCE_DIR "/modules"}); 21 | fcitx::Log::setLogRule("*=5"); 22 | 23 | char arg0[] = "testcloudpinyin"; 24 | char arg1[] = "--disable=all"; 25 | char arg2[] = "--enable=cloudpinyin"; 26 | char *argv[] = {arg0, arg1, arg2}; 27 | fcitx::Instance instance(FCITX_ARRAY_SIZE(argv), argv); 28 | instance.addonManager().registerDefaultLoader(nullptr); 29 | 30 | int returned = 0; 31 | instance.eventDispatcher().schedule([&instance, &returned]() { 32 | auto callback = [&instance, &returned](const std::string &pinyin, 33 | const std::string &hanzi) { 34 | std::cout << "Pinyin: " << pinyin << std::endl; 35 | std::cout << "Hanzi: " << hanzi << std::endl; 36 | returned++; 37 | if (returned == 1) { 38 | instance.exit(); 39 | } 40 | }; 41 | auto *cloudpinyin = instance.addonManager().addon("cloudpinyin", true); 42 | cloudpinyin->call("nihao", callback); 43 | cloudpinyin->call("ceshi", callback); 44 | }); 45 | instance.exec(); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test/testdir.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017~2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | */ 6 | #ifndef _TEST_TESTDIR_H_ 7 | #define _TEST_TESTDIR_H_ 8 | 9 | #define TESTING_SOURCE_DIR "@CMAKE_SOURCE_DIR@" 10 | #define TESTING_BINARY_DIR "@CMAKE_BINARY_DIR@" 11 | 12 | #endif // _TEST_TESTDIR_H_ 13 | -------------------------------------------------------------------------------- /test/testfullwidth.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020-2020 Vifly 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "testdir.h" 8 | #include "testfrontend_public.h" 9 | #include "testim_public.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace fcitx; 21 | 22 | void scheduleEvent(Instance *instance) { 23 | instance->eventDispatcher().schedule([instance]() { 24 | auto *fullwidth = instance->addonManager().addon("fullwidth", true); 25 | FCITX_ASSERT(fullwidth); 26 | RawConfig config; 27 | config.setValueByPath("Hotkey/0", "Control+period"); 28 | fullwidth->setConfig(config); 29 | }); 30 | 31 | instance->eventDispatcher().schedule([instance]() { 32 | auto testfrontend = instance->addonManager().addon("testfrontend"); 33 | auto testim = instance->addonManager().addon("testim"); 34 | auto *action = 35 | instance->userInterfaceManager().lookupAction("fullwidth"); 36 | 37 | testim->call([action](const InputMethodEntry &, 38 | KeyEvent &keyEvent) { 39 | if (keyEvent.key().states() != KeyState::NoState || 40 | keyEvent.isRelease()) { 41 | return; 42 | } 43 | auto s = Key::keySymToUTF8(keyEvent.key().sym()); 44 | if (!s.empty()) { 45 | if (!action->isParent(&keyEvent.inputContext()->statusArea())) { 46 | keyEvent.inputContext()->statusArea().addAction( 47 | StatusGroup::InputMethod, action); 48 | action->activate(keyEvent.inputContext()); 49 | } 50 | 51 | // Test multiple character string 52 | if (s == "c") { 53 | s = "abcd"; 54 | } else if (s == "d") { 55 | s = "test!"; 56 | } 57 | keyEvent.inputContext()->commitString(s); 58 | keyEvent.filterAndAccept(); 59 | } 60 | }); 61 | 62 | auto uuid = 63 | testfrontend->call("testapp"); 64 | 65 | testfrontend->call("a"); 66 | testfrontend->call(uuid, Key("a"), false); 67 | testfrontend->call("b"); 68 | testfrontend->call(uuid, Key("b"), false); 69 | testfrontend->call("~"); 70 | testfrontend->call(uuid, Key("~"), false); 71 | testfrontend->call("?"); 72 | testfrontend->call(uuid, Key("?"), false); 73 | 74 | testfrontend->call("abcd"); 75 | testfrontend->call(uuid, Key("c"), false); 76 | testfrontend->call("test!"); 77 | testfrontend->call(uuid, Key("d"), false); 78 | 79 | // Test toggle key 80 | testfrontend->call(uuid, Key("Control+period"), 81 | false); 82 | testfrontend->call("e"); 83 | testfrontend->call(uuid, Key("e"), false); 84 | testfrontend->call(","); 85 | testfrontend->call(uuid, Key(","), false); 86 | 87 | instance->exit(); 88 | }); 89 | } 90 | 91 | void runInstance() {} 92 | 93 | int main() { 94 | setupTestingEnvironment(TESTING_BINARY_DIR, 95 | {"bin", StandardPaths::fcitxPath("addondir")}, 96 | {"test"}); 97 | fcitx::Log::setLogRule("*=5"); 98 | 99 | char arg0[] = "testfullwidth"; 100 | char arg1[] = "--disable=all"; 101 | char arg2[] = "--enable=testim,testfrontend,fullwidth"; 102 | char *argv[] = {arg0, arg1, arg2}; 103 | Instance instance(FCITX_ARRAY_SIZE(argv), argv); 104 | instance.addonManager().registerDefaultLoader(nullptr); 105 | scheduleEvent(&instance); 106 | instance.exec(); 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /test/testpinyinhelper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "pinyinhelper_public.h" 8 | #include "testdir.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main() { 15 | fcitx::setupTestingEnvironmentPath(TESTING_BINARY_DIR, {"bin"}, 16 | {TESTING_BINARY_DIR "/modules"}); 17 | fcitx::AddonManager manager(TESTING_BINARY_DIR "/modules/pinyinhelper"); 18 | manager.registerDefaultLoader(nullptr); 19 | manager.load(); 20 | auto *pinyinhelper = manager.addon("pinyinhelper", true); 21 | FCITX_ASSERT(pinyinhelper); 22 | std::vector expect{"nǐ"}; 23 | auto result = pinyinhelper->call( 24 | fcitx::utf8::getChar("你")); 25 | for (auto &s : result) { 26 | FCITX_INFO() << s << " "; 27 | } 28 | FCITX_ASSERT(result == expect); 29 | auto result2 = 30 | pinyinhelper->call("2511", 3); 31 | for (auto &s : result2) { 32 | FCITX_INFO() 33 | << s.first << " " 34 | << pinyinhelper->call( 35 | s.second); 36 | } 37 | auto result3 = 38 | pinyinhelper->call("szhh", 3); 39 | FCITX_ASSERT(result2 == result3); 40 | 41 | auto result4 = 42 | pinyinhelper->call("你"); 43 | FCITX_ASSERT(result4 == "3235234") << result4; 44 | auto result5 = 45 | pinyinhelper->call("54321"); 46 | FCITX_ASSERT(result5 == "𠃍㇏丿丨一"); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/testpunctuation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2017-2017 CSSlayer 3 | * 4 | * SPDX-License-Identifier: LGPL-2.1-or-later 5 | * 6 | */ 7 | #include "punctuation_public.h" 8 | #include "testdir.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main() { 15 | fcitx::setupTestingEnvironmentPath( 16 | TESTING_BINARY_DIR, {"bin"}, 17 | {TESTING_BINARY_DIR "/modules", TESTING_SOURCE_DIR "/modules"}); 18 | fcitx::AddonManager manager(TESTING_BINARY_DIR "/modules/punctuation"); 19 | manager.registerDefaultLoader(nullptr); 20 | manager.load(); 21 | auto *punctuation = manager.addon("punctuation", true); 22 | FCITX_ASSERT(punctuation); 23 | FCITX_ASSERT( 24 | punctuation->call("zh_CN", ',') 25 | .first == ","); 26 | FCITX_ASSERT( 27 | punctuation->call("zh_CN", '"') 28 | .first == "“"); 29 | FCITX_ASSERT( 30 | punctuation->call("zh_CN", '"') 31 | .second == "”"); 32 | FCITX_ASSERT( 33 | punctuation->call( 34 | "zh_CN", '#') == std::vector{"#", "#"}); 35 | fcitx::RawConfig config; 36 | config["Entries"]["0"]["Key"] = "*"; 37 | config["Entries"]["0"]["Mapping"] = "X"; 38 | config["Entries"]["0"]["AltMapping"] = ""; 39 | config["Entries"]["1"]["Key"] = "\""; 40 | config["Entries"]["1"]["Mapping"] = "「"; 41 | config["Entries"]["1"]["AltMapping"] = "」"; 42 | punctuation->setSubConfig("punctuationmap/zh_CN", config); 43 | FCITX_ASSERT( 44 | punctuation->call("zh_CN", '*') 45 | .first == "X"); 46 | FCITX_ASSERT( 47 | punctuation->call("zh_CN", '"') 48 | .first == "「"); 49 | FCITX_ASSERT( 50 | punctuation->call("zh_CN", '"') 51 | .second == "」"); 52 | FCITX_ASSERT( 53 | punctuation->call("zh_CN", ',') 54 | .first == ""); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /test/testsymboldictionary.cpp: -------------------------------------------------------------------------------- 1 | #include "../im/pinyin/symboldictionary.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace fcitx; 8 | 9 | constexpr std::string_view testInput = R"TEST( 10 | AAA BBB 11 | "CDEF G" H 12 | X "Y Z" 13 | "Y""12" 14 | "Y" "34" 15 | "Y" "56" 16 | )TEST"; 17 | 18 | void test_basic() { 19 | std::stringstream ss; 20 | 21 | ss << testInput; 22 | 23 | SymbolDict dict; 24 | dict.load(ss); 25 | auto *result = dict.lookup("P"); 26 | FCITX_ASSERT(!result); 27 | 28 | result = dict.lookup("AAA"); 29 | FCITX_ASSERT(*result == std::vector{"BBB"}); 30 | 31 | result = dict.lookup("CDEF G"); 32 | FCITX_ASSERT(*result == std::vector{"H"}); 33 | 34 | result = dict.lookup("Y"); 35 | FCITX_ASSERT(*result == std::vector{"34", "56"}); 36 | 37 | result = dict.lookup("X"); 38 | FCITX_ASSERT(*result == std::vector{"Y Z"}); 39 | } 40 | 41 | int main() { 42 | test_basic(); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test/valgrind_suppress: -------------------------------------------------------------------------------- 1 | { 2 | ignore_libcrypto_conditional_jump_errors 3 | Memcheck:Leak 4 | ... 5 | obj:*/libcrypto.so.* 6 | } 7 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(scel2org5 scel2org5.cpp) 2 | 3 | target_link_libraries(scel2org5 Fcitx5::Utils) 4 | install(TARGETS scel2org5 DESTINATION ${CMAKE_INSTALL_BINDIR}) 5 | --------------------------------------------------------------------------------