aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Koivikko <jarkko.koivikko@code-q.fi>2015-10-15 10:18:22 +0300
committerJarkko Koivikko <jarkko.koivikko@code-q.fi>2015-10-27 10:13:51 +0000
commit81c0d7d4df40c1130a8e7c98411c045b7eafc475 (patch)
treebee9a753c20b80d6630f39fee86e7758f2aae926
parent251a86bd64856c2f48ac62f8f8747ddf21982876 (diff)
Add Cangjie input method for Traditional Chinese
This change adds Cangjie input method for Traditional Chinese. The input method is based on the TCIME input method for Android. https://code.google.com/p/android-traditional-chinese-ime/ The Cangjie input method is enabled by adding CONFIG+=tcime into qmake command line. The version of the Cangjie input is v3. Change-Id: Ibc49484d1277c332fc17e9b49b4227256ad88d5a Reviewed-by: Liang Qi <liang.qi@theqtcompany.com> Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com> Reviewed-by: Rainer Keller <rainer.keller@theqtcompany.com>
-rw-r--r--src/src.pro5
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/COPYING92
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.cpp141
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.h54
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/cangjietable.cpp111
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/cangjietable.h79
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/data/java/dict_cangjie.datbin0 -> 58525 bytes
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/data/java/dict_phrases.datbin0 -> 133359 bytes
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/data/qt/dict_cangjie.datbin0 -> 54840 bytes
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/data/qt/dict_phrases.datbin0 -> 133304 bytes
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/phrasedictionary.cpp66
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/phrasedictionary.h43
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/tcime.pro29
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.classbin0 -> 5163 bytes
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.java201
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/worddictionary.cpp43
-rw-r--r--src/virtualkeyboard/3rdparty/tcime/worddictionary.h61
-rw-r--r--src/virtualkeyboard/content/components/ModeKey.qml52
-rw-r--r--src/virtualkeyboard/content/content.qrc1
-rw-r--r--src/virtualkeyboard/content/layouts/zh_TW/main.qml393
-rw-r--r--src/virtualkeyboard/content/layouts/zh_TW/symbols.qml283
-rw-r--r--src/virtualkeyboard/content/layouts_traditional_chinese.qrc12
-rw-r--r--src/virtualkeyboard/content/styles/default/style.qml68
-rw-r--r--src/virtualkeyboard/content/styles/retro/style.qml61
-rw-r--r--src/virtualkeyboard/declarativeinputengine.cpp3
-rw-r--r--src/virtualkeyboard/declarativeinputengine.h1
-rw-r--r--src/virtualkeyboard/declarativeshifthandler.cpp10
-rw-r--r--src/virtualkeyboard/doc/src/build.qdoc8
-rw-r--r--src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc3
-rw-r--r--src/virtualkeyboard/plugin.cpp10
-rw-r--r--src/virtualkeyboard/styles/KeyboardStyle.qml12
-rw-r--r--src/virtualkeyboard/tcinputmethod.cpp330
-rw-r--r--src/virtualkeyboard/tcinputmethod.h57
-rw-r--r--src/virtualkeyboard/virtualkeyboard.pro19
-rw-r--r--tests/auto/inputpanel/data/inputpanel/inputpanel.qml7
-rw-r--r--tests/auto/inputpanel/data/tst_inputpanel.qml53
36 files changed, 2298 insertions, 10 deletions
diff --git a/src/src.pro b/src/src.pro
index 12dbd983..ca5b8481 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -19,6 +19,11 @@ pinyin {
virtualkeyboard.depends += sub-virtualkeyboard-3rdparty-pinyin
}
+tcime {
+ SUBDIRS += virtualkeyboard/3rdparty/tcime
+ virtualkeyboard.depends += sub-virtualkeyboard-3rdparty-tcime
+}
+
lipi-toolkit {
SUBDIRS += virtualkeyboard/3rdparty/lipi-toolkit
virtualkeyboard.depends += sub-virtualkeyboard-3rdparty-lipi-toolkit
diff --git a/src/virtualkeyboard/3rdparty/tcime/COPYING b/src/virtualkeyboard/3rdparty/tcime/COPYING
new file mode 100644
index 00000000..606b8475
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/COPYING
@@ -0,0 +1,92 @@
+The project in general is under the following licenses:
+
+================================================================================
+Copyright 2010 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+================================================================================
+
+File dict_phrases.dat is built from libTabe; the licenses of libTabe is:
+
+================================================================================
+/*
+ * Copyrighy (c) 1999 TaBE Project.
+ * Copyright (c) 1999 Pai-Hsiang Hsiao.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * . Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * . Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * . Neither the name of the TaBE Project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Computer Systems and Communication Lab,
+ * Institute of Information Science, Academia Sinica.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * . Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * . Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * . Neither the name of the Computer Systems and Communication Lab
+ * nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+Copyright 1996 Chih-Hao Tsai @ Beckman Institute, University of Illinois
+c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4
+================================================================================
+
diff --git a/src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.cpp b/src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.cpp
new file mode 100644
index 00000000..1a50d371
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.cpp
@@ -0,0 +1,141 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cangjiedictionary.h"
+#include "cangjietable.h"
+
+using namespace tcime;
+
+bool CangjieDictionary::_simplified = false;
+
+CangjieDictionary::CangjieDictionary() :
+ WordDictionary(),
+ _collator(QLocale("zh_TW"))
+{
+}
+
+bool CangjieDictionary::simplified() const
+{
+ return _simplified;
+}
+
+void CangjieDictionary::setSimplified(bool simplified)
+{
+ _simplified = simplified;
+}
+
+QStringList CangjieDictionary::getWords(const QString &input) const
+{
+ // Look up the index in the dictionary for the specified input.
+ int primaryIndex = CangjieTable::getPrimaryIndex(input);
+ if (primaryIndex < 0 || primaryIndex >= dictionary().size())
+ return QStringList();
+
+ // [25 * 26] char[] array; each primary entry points to a char[]
+ // containing words with the same primary index; then words can be looked up
+ // by their secondary index stored at the beginning of each char[].
+ const DictionaryEntry &data = dictionary()[primaryIndex];
+ if (data.isEmpty())
+ return QStringList();
+
+ if (_simplified)
+ // Sort words of this primary index for simplified-cangjie.
+ return sortWords(data);
+
+ int secondaryIndex = CangjieTable::getSecondaryIndex(input);
+ if (secondaryIndex < 0)
+ return QStringList();
+
+ // Find words match this secondary index for cangjie.
+ return searchWords(secondaryIndex, data);
+}
+
+class DictionaryComparator
+{
+public:
+ explicit DictionaryComparator(const std::vector<QCollatorSortKey> &sortKeys) :
+ sortKeys(sortKeys)
+ {}
+
+ bool operator()(int a, int b)
+ {
+ return sortKeys[a] < sortKeys[b];
+ }
+
+private:
+ const std::vector<QCollatorSortKey> &sortKeys;
+};
+
+QStringList CangjieDictionary::sortWords(const DictionaryEntry &data) const
+{
+ int length = data.size() / 2;
+ std::vector<QCollatorSortKey> sortKeys;
+ QVector<int> keys;
+ sortKeys.reserve(length);
+ keys.reserve(length);
+ for (int i = 0; i < length; ++i) {
+ sortKeys.push_back(_collator.sortKey(data[length + i]));
+ keys.append(i);
+ }
+ DictionaryComparator dictionaryComparator(sortKeys);
+ std::sort(keys.begin(), keys.end(), dictionaryComparator);
+
+ QStringList words;
+ for (int i = 0; i < length; ++i)
+ words.append(data[length + keys[i]]);
+
+ return words;
+}
+
+QStringList CangjieDictionary::searchWords(int secondaryIndex, const DictionaryEntry &data) const
+{
+ int length = data.size() / 2;
+
+ DictionaryEntry::ConstIterator start = data.constBegin();
+ DictionaryEntry::ConstIterator end = start + length;
+ DictionaryEntry::ConstIterator rangeStart = qBinaryFind(start, end, (DictionaryWord)secondaryIndex);
+ if (rangeStart == end)
+ return QStringList();
+
+ // There may be more than one words with the same index; look up words with
+ // the same secondary index.
+ while (rangeStart != start) {
+ if (*(rangeStart - 1) != (DictionaryWord)secondaryIndex)
+ break;
+ rangeStart--;
+ }
+
+ DictionaryEntry::ConstIterator rangeEnd = rangeStart + 1;
+ while (rangeEnd != end) {
+ if (*rangeEnd != (DictionaryWord)secondaryIndex)
+ break;
+ rangeEnd++;
+ }
+
+ QStringList words;
+ words.reserve(rangeEnd - rangeStart);
+ for (DictionaryEntry::ConstIterator rangeIndex = rangeStart; rangeIndex < rangeEnd; ++rangeIndex) {
+ DictionaryEntry::ConstIterator item(rangeIndex + length);
+ words.append(*item);
+ }
+
+ return words;
+}
diff --git a/src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.h b/src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.h
new file mode 100644
index 00000000..b87013a9
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/cangjiedictionary.h
@@ -0,0 +1,54 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CANGJIEDICTIONARY_H
+#define CANGJIEDICTIONARY_H
+
+#include "worddictionary.h"
+#include <QCollator>
+
+namespace tcime {
+
+/**
+ * Extends WordDictionary to provide cangjie word-suggestions.
+ */
+class CangjieDictionary : public WordDictionary
+{
+public:
+ CangjieDictionary();
+
+ bool simplified() const;
+ void setSimplified(bool simplified);
+
+ QStringList getWords(const QString &input) const;
+
+private:
+ QStringList sortWords(const DictionaryEntry &data) const;
+ QStringList searchWords(int secondaryIndex, const DictionaryEntry &data) const;
+
+private:
+ QCollator _collator;
+ static bool _simplified;
+};
+
+}
+
+#endif // CANGJIEDICTIONARY_H
diff --git a/src/virtualkeyboard/3rdparty/tcime/cangjietable.cpp b/src/virtualkeyboard/3rdparty/tcime/cangjietable.cpp
new file mode 100644
index 00000000..ee8ae4f8
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/cangjietable.cpp
@@ -0,0 +1,111 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cangjietable.h"
+
+using namespace tcime;
+
+const int CangjieTable::BASE_NUMBER = 26;
+const int CangjieTable::MAX_CODE_LENGTH = 5;
+const int CangjieTable::MAX_SIMPLIFIED_CODE_LENGTH = 2;
+
+const QMap<QChar, int> &CangjieTable::letters()
+{
+ static QMap<QChar, int> letters;
+ if (letters.isEmpty()) {
+ int i = 1;
+ letters.insert(0x65e5, i++);
+ letters.insert(0x6708, i++);
+ letters.insert(0x91d1, i++);
+ letters.insert(0x6728, i++);
+ letters.insert(0x6c34, i++);
+ letters.insert(0x706b, i++);
+ letters.insert(0x571f, i++);
+ letters.insert(0x7af9, i++);
+ letters.insert(0x6208, i++);
+ letters.insert(0x5341, i++);
+ letters.insert(0x5927, i++);
+ letters.insert(0x4e2d, i++);
+ letters.insert(0x4e00, i++);
+ letters.insert(0x5f13, i++);
+ letters.insert(0x4eba, i++);
+ letters.insert(0x5fc3, i++);
+ letters.insert(0x624b, i++);
+ letters.insert(0x53e3, i++);
+ letters.insert(0x5c38, i++);
+ letters.insert(0x5eff, i++);
+ letters.insert(0x5c71, i++);
+ letters.insert(0x5973, i++);
+ letters.insert(0x7530, i++);
+ letters.insert(0x96e3, i++);
+ letters.insert(0x535c, i++);
+ }
+ return letters;
+}
+
+bool CangjieTable::isLetter(const QChar &c)
+{
+ static const QMap<QChar, int> &letters = CangjieTable::letters();
+ return letters.contains(c);
+}
+
+int CangjieTable::getPrimaryIndex(const QString &code)
+{
+ static const QMap<QChar, int> &letters = CangjieTable::letters();
+ int length = code.length();
+ if ((length < 1) || (length > MAX_CODE_LENGTH))
+ return -1;
+
+ QChar c = code.at(0);
+ if (!isLetter(c))
+ return -1;
+
+ // The first letter cannot be absent in the code; therefore, the numerical
+ // index of the first letter starts from 0 instead.
+ int index = (letters[c] - 1) * BASE_NUMBER;
+ if (length < 2)
+ return index;
+
+ c = code.at(length - 1);
+ if (!isLetter(c))
+ return -1;
+
+ return index + letters[c];
+}
+
+int CangjieTable::getSecondaryIndex(const QString &code)
+{
+ static const QMap<QChar, int> &letters = CangjieTable::letters();
+ int index = 0;
+ int last = code.length() - 1;
+ for (int i = 1; i < last; i++) {
+ QChar c = code.at(i);
+ if (!isLetter(c))
+ return -1;
+ index = index * BASE_NUMBER + letters[c];
+ }
+
+ int maxEnd = MAX_CODE_LENGTH - 1;
+ for (int i = last; i < maxEnd; i++)
+ index = index * BASE_NUMBER;
+
+ return index;
+}
diff --git a/src/virtualkeyboard/3rdparty/tcime/cangjietable.h b/src/virtualkeyboard/3rdparty/tcime/cangjietable.h
new file mode 100644
index 00000000..54adced3
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/cangjietable.h
@@ -0,0 +1,79 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CANGJIETABLE_H
+#define CANGJIETABLE_H
+
+#include <QMap>
+#include <QChar>
+#include <QString>
+
+namespace tcime {
+
+/**
+ * Defines cangjie letters and calculates the index of the given cangjie code.
+ */
+class CangjieTable
+{
+ Q_DISABLE_COPY(CangjieTable)
+ CangjieTable() {}
+
+ // Cangjie 25 letters with number-index starting from 1:
+ // 日月金木水火土竹戈十大中一弓人心手口尸廿山女田難卜
+ static const QMap<QChar, int> &letters();
+ static const int BASE_NUMBER;
+
+public:
+
+ // Cangjie codes contain at most five letters. A cangjie code can be
+ // converted to a numerical code by the number-index of each letter.
+ // The absent letter will be indexed as 0 if the cangjie code contains less
+ // than five-letters.
+ static const int MAX_CODE_LENGTH;
+ static const int MAX_SIMPLIFIED_CODE_LENGTH;
+
+ /**
+ * Returns {@code true} only if the given character is a valid cangjie letter.
+ */
+ static bool isLetter(const QChar &c);
+
+ /**
+ * Returns the primary index calculated by the first and last letter of
+ * the given cangjie code.
+ *
+ * @param code should not be null.
+ * @return -1 for invalid code.
+ */
+ static int getPrimaryIndex(const QString &code);
+
+ /**
+ * Returns the secondary index calculated by letters between the first and
+ * last letter of the given cangjie code.
+ *
+ * @param code should not be null.
+ * @return -1 for invalid code.
+ */
+ static int getSecondaryIndex(const QString &code);
+};
+
+}
+
+#endif // CANGJIETABLE_H
diff --git a/src/virtualkeyboard/3rdparty/tcime/data/java/dict_cangjie.dat b/src/virtualkeyboard/3rdparty/tcime/data/java/dict_cangjie.dat
new file mode 100644
index 00000000..1c692c48
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/data/java/dict_cangjie.dat
Binary files differ
diff --git a/src/virtualkeyboard/3rdparty/tcime/data/java/dict_phrases.dat b/src/virtualkeyboard/3rdparty/tcime/data/java/dict_phrases.dat
new file mode 100644
index 00000000..0b34ee1f
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/data/java/dict_phrases.dat
Binary files differ
diff --git a/src/virtualkeyboard/3rdparty/tcime/data/qt/dict_cangjie.dat b/src/virtualkeyboard/3rdparty/tcime/data/qt/dict_cangjie.dat
new file mode 100644
index 00000000..f99ed965
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/data/qt/dict_cangjie.dat
Binary files differ
diff --git a/src/virtualkeyboard/3rdparty/tcime/data/qt/dict_phrases.dat b/src/virtualkeyboard/3rdparty/tcime/data/qt/dict_phrases.dat
new file mode 100644
index 00000000..463301f9
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/data/qt/dict_phrases.dat
Binary files differ
diff --git a/src/virtualkeyboard/3rdparty/tcime/phrasedictionary.cpp b/src/virtualkeyboard/3rdparty/tcime/phrasedictionary.cpp
new file mode 100644
index 00000000..cdeaecdd
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/phrasedictionary.cpp
@@ -0,0 +1,66 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "phrasedictionary.h"
+
+using namespace tcime;
+
+PhraseDictionary::PhraseDictionary() :
+ WordDictionary()
+{
+}
+
+QStringList PhraseDictionary::getWords(const QString &input) const
+{
+ if (input.length() != 1)
+ return QStringList();
+
+ // Phrases are stored in an array consisting of three character arrays.
+ // char[0][] contains a char[] of words to look for phrases.
+ // char[2][] contains a char[] of following words for char[0][].
+ // char[1][] contains offsets of char[0][] words to map its following words.
+ // For example, there are 5 phrases: Aa, Aa', Bb, Bb', Cc.
+ // char[0][] { A, B, C }
+ // char[1][] { 0, 2, 4 }
+ // char[2][] { a, a', b, b', c}
+ const Dictionary &dict = dictionary();
+ if (dict.length() != 3)
+ return QStringList();
+
+ const DictionaryEntry &words = dict[0];
+
+ DictionaryEntry::ConstIterator word = qBinaryFind(words, input.at(0));
+ if (word == words.constEnd())
+ return QStringList();
+
+ int index = word - words.constBegin();
+ const DictionaryEntry &offsets = dict[1];
+ const DictionaryEntry &phrases = dict[2];
+ int offset = (int)offsets[index].unicode();
+ int count = (index < offsets.length() - 1) ?
+ ((int)offsets[index + 1].unicode() - offset) : (phrases.length() - offset);
+
+ QStringList result;
+ for (int i = 0; i < count; ++i)
+ result.append(phrases[offset + i]);
+
+ return result;
+}
diff --git a/src/virtualkeyboard/3rdparty/tcime/phrasedictionary.h b/src/virtualkeyboard/3rdparty/tcime/phrasedictionary.h
new file mode 100644
index 00000000..06fe9578
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/phrasedictionary.h
@@ -0,0 +1,43 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PHRASEDICTIONARY_H
+#define PHRASEDICTIONARY_H
+
+#include "worddictionary.h"
+
+namespace tcime {
+
+/**
+ * Reads a phrase dictionary and provides following-word suggestions as a list
+ * of characters for the given character.
+ */
+class PhraseDictionary : public WordDictionary
+{
+public:
+ PhraseDictionary();
+
+ QStringList getWords(const QString &input) const;
+};
+
+}
+
+#endif // PHRASEDICTIONARY_H
diff --git a/src/virtualkeyboard/3rdparty/tcime/tcime.pro b/src/virtualkeyboard/3rdparty/tcime/tcime.pro
new file mode 100644
index 00000000..65261f46
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/tcime.pro
@@ -0,0 +1,29 @@
+TEMPLATE = lib
+QT -= gui
+TARGET = tcime
+CONFIG += staticlib
+
+build_pass {
+ CONFIG(debug, debug|release): SUBPATH = debug
+ else: SUBPATH = release
+} else {
+ debug_and_release: CONFIG += build_all
+}
+
+DESTDIR = $$SUBPATH
+
+SOURCES += \
+ cangjiedictionary.cpp \
+ cangjietable.cpp \
+ phrasedictionary.cpp \
+ worddictionary.cpp
+
+HEADERS += \
+ cangjiedictionary.h \
+ cangjietable.h \
+ phrasedictionary.h \
+ worddictionary.h
+
+OTHER_FILES += \
+ data/dict_cangjie.dat \
+ data/dict_phrases.dat
diff --git a/src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.class b/src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.class
new file mode 100644
index 00000000..d1e70d8e
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.class
Binary files differ
diff --git a/src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.java b/src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.java
new file mode 100644
index 00000000..6dd81212
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/tools/dict2qt.java
@@ -0,0 +1,201 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd
+** All rights reserved.
+** For any questions to The Qt Company, please use contact form at http://qt.io
+**
+** This file is part of the Qt Virtual Keyboard module.
+**
+** Licensees holding valid commercial license for Qt may use this file in
+** accordance with the Qt License Agreement provided with the Software
+** or, alternatively, in accordance with the terms contained in a written
+** agreement between you and The Qt Company.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.io
+**
+******************************************************************************/
+
+import java.io.BufferedInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class dict2qt {
+
+ public static void main(String[] args) {
+ boolean showHelp = false;
+ boolean showUsage = false;
+ boolean littleEndian = false;
+ String outputFileName = "";
+ String inputFileName = "";
+ File inputFile = null;
+
+ if (args.length > 0) {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].startsWith("-")) {
+ if (args[i].compareTo("-h") == 0) {
+ showHelp = true;
+ showUsage = true;
+ break;
+ } else if (args[i].compareTo("-o") == 0) {
+ if (++i >= args.length) {
+ System.err.println("Error: missing argument <output file>");
+ showUsage = true;
+ break;
+ }
+ outputFileName = args[i];
+ } else if (args[i].compareTo("-le") == 0) {
+ littleEndian = true;
+ } else {
+ System.err.println("Error: unknown option '" + args[i] + "'");
+ showUsage = true;
+ break;
+ }
+ } else if (inputFileName.isEmpty() && i + 1 == args.length) {
+ inputFileName = args[i];
+ } else {
+ System.err.println("Error: unexpected argument '" + args[i] + "'");
+ showUsage = true;
+ break;
+ }
+ }
+
+ if (!showUsage && !showHelp) {
+ if (!inputFileName.isEmpty()) {
+ inputFile = new File(inputFileName);
+ if (!inputFile.exists()) {
+ System.err.println("Error: input file does not exist '" + inputFileName + "'");
+ return;
+ }
+ if (outputFileName.isEmpty())
+ outputFileName = inputFileName;
+ }
+
+ if (inputFile == null) {
+ System.err.println("Error: missing argument file");
+ showUsage = true;
+ }
+ }
+ } else {
+ showUsage = true;
+ }
+
+ if (showUsage || showHelp) {
+ if (showHelp) {
+ System.err.println("TCIME dictionary converter for Qt Virtual Keyboard");
+ System.err.println("");
+ System.err.println("Copyright (C) 2015 The Qt Company Ltd - All rights reserved.");
+ System.err.println("");
+ System.err.println(" This utility converts TCIME dictionaries to Qt compatible");
+ System.err.println(" format. The dictionaries are basically Java char[][] arrays");
+ System.err.println(" serialized to file with ObjectOutputStream.");
+ System.err.println("");
+ System.err.println(" The corresponding data format in the Qt dictionary is");
+ System.err.println(" QVector<QVector<ushort>>. The byte order is set to big endian");
+ System.err.println(" by default, but can be changed with -le option.");
+ }
+ if (showUsage) {
+ System.err.println("");
+ System.err.println("Usage: java dict2qt [options] file");
+ System.err.println("Options:");
+ System.err.println(" -o <output file> Place the output into <output file>");
+ System.err.println(" -le Change byte order to little endian");
+ System.err.println(" -h Display help");
+ }
+ return;
+ }
+
+ char[][] dictionary = null;
+ try {
+ dictionary = loadDictionary(new FileInputStream(inputFile));
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return;
+ }
+ if (dictionary == null)
+ return;
+
+ int dictionarySize = calculateDictionarySize(dictionary);
+ ByteBuffer buffer = ByteBuffer.allocate(dictionarySize);
+ if (littleEndian)
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+ else
+ buffer.order(ByteOrder.BIG_ENDIAN);
+ buffer.putInt(dictionary.length);
+ for (int i = 0; i < dictionary.length; i++) {
+ char[] data = dictionary[i];
+ if (data != null) {
+ buffer.putInt(data.length);
+ for (int j = 0; j < data.length; j++) {
+ buffer.putChar(data[j]);
+ }
+ } else {
+ buffer.putInt(0);
+ }
+ }
+
+ byte[] bytes = buffer.array();
+ DataOutputStream dos = null;
+ try {
+ File outputFile = new File(outputFileName);
+ FileOutputStream os = new FileOutputStream(outputFile);
+ dos = new DataOutputStream(os);
+ dos.write(bytes, 0, buffer.position());
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (dos != null) {
+ try {
+ dos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ static char[][] loadDictionary(InputStream ins) {
+ char[][] result = null;
+ ObjectInputStream oin = null;
+ try {
+ BufferedInputStream bis = new BufferedInputStream(ins);
+ oin = new ObjectInputStream(bis);
+ result = (char[][]) oin.readObject();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (oin != null) {
+ try {
+ oin.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return result;
+ }
+
+ static int calculateDictionarySize(final char[][] dictionary) {
+ int result = 4;
+ for (int i = 0; i < dictionary.length; i++) {
+ char[] data = dictionary[i];
+ result += 4;
+ if (data != null)
+ result += data.length * 2;
+ }
+ return result;
+ }
+
+}
diff --git a/src/virtualkeyboard/3rdparty/tcime/worddictionary.cpp b/src/virtualkeyboard/3rdparty/tcime/worddictionary.cpp
new file mode 100644
index 00000000..6bc0a9e2
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/worddictionary.cpp
@@ -0,0 +1,43 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "worddictionary.h"
+#include <QDataStream>
+#include <QFile>
+
+using namespace tcime;
+
+bool WordDictionary::load(const QString &fileName, bool littleEndian)
+{
+ _dictionary.clear();
+
+ QFile dictionaryFile(fileName);
+ if (!dictionaryFile.open(QIODevice::ReadOnly))
+ return false;
+
+ QDataStream ds(&dictionaryFile);
+ if (littleEndian)
+ ds.setByteOrder(QDataStream::LittleEndian);
+ Q_ASSERT((ds.byteOrder() == QDataStream::LittleEndian) == littleEndian);
+ ds >> _dictionary;
+
+ return !_dictionary.isEmpty();
+}
diff --git a/src/virtualkeyboard/3rdparty/tcime/worddictionary.h b/src/virtualkeyboard/3rdparty/tcime/worddictionary.h
new file mode 100644
index 00000000..3f1ea43e
--- /dev/null
+++ b/src/virtualkeyboard/3rdparty/tcime/worddictionary.h
@@ -0,0 +1,61 @@
+/*
+ * Qt implementation of TCIME library
+ * This file is part of the Qt Virtual Keyboard module.
+ * Contact: http://www.qt.io/licensing/
+ *
+ * Copyright (C) 2015 The Qt Company
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WORDDICTIONARY_H
+#define WORDDICTIONARY_H
+
+#include <QVector>
+#include <QString>
+#include <QStringList>
+
+namespace tcime {
+
+/**
+ * Reads a word-dictionary and provides word-suggestions as a list of characters
+ * for the specified input.
+ */
+class WordDictionary
+{
+ Q_DISABLE_COPY(WordDictionary)
+
+protected:
+ typedef QChar DictionaryWord;
+ typedef QVector<DictionaryWord> DictionaryEntry;
+ typedef QVector<DictionaryEntry> Dictionary;
+
+ const Dictionary &dictionary() const { return _dictionary; }
+
+public:
+ WordDictionary() {}
+ virtual ~WordDictionary() {}
+
+ bool isEmpty() const { return _dictionary.isEmpty(); }
+
+ virtual bool load(const QString &fileName, bool littleEndian = false);
+ virtual QStringList getWords(const QString &input) const = 0;
+
+private:
+ Dictionary _dictionary;
+};
+
+}
+
+#endif // WORDDICTIONARY_H
diff --git a/src/virtualkeyboard/content/components/ModeKey.qml b/src/virtualkeyboard/content/components/ModeKey.qml
new file mode 100644
index 00000000..da975ecd
--- /dev/null
+++ b/src/virtualkeyboard/content/components/ModeKey.qml
@@ -0,0 +1,52 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd
+** All rights reserved.
+** For any questions to The Qt Company, please use contact form at http://qt.io
+**
+** This file is part of the Qt Virtual Keyboard module.
+**
+** Licensees holding valid commercial license for Qt may use this file in
+** accordance with the Qt License Agreement provided with the Software
+** or, alternatively, in accordance with the terms contained in a written
+** agreement between you and The Qt Company.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.io
+**
+******************************************************************************/
+
+import QtQuick 2.0
+
+/*!
+ \qmltype ModeKey
+ \inqmlmodule QtQuick.Enterprise.VirtualKeyboard
+ \ingroup qtvirtualkeyboard-qml
+ \inherits Key
+ \since QtQuick.Enterprise.VirtualKeyboard 2.0
+
+ \brief Generic mode key for keyboard layouts.
+
+ This key provides generic mode button functionality.
+
+ A key press toggles the current mode without emitting key event
+ for input method processing.
+
+ ModeKey can be used in situations where a particular mode is switched
+ "ON / OFF", and where the mode change does not require changing the
+ keyboard layout. When this component is used, the \l { BaseKey::displayText } { displayText } should
+ remain the same regardless of the mode, because the keyboard style
+ visualizes the status.
+*/
+
+Key {
+ /*! This property provides the current mode.
+
+ The default is false.
+ */
+ property bool mode
+ noKeyEvent: true
+ functionKey: true
+ onClicked: mode = !mode
+ keyPanelDelegate: keyboard.style ? keyboard.style.modeKeyPanel : undefined
+}
diff --git a/src/virtualkeyboard/content/content.qrc b/src/virtualkeyboard/content/content.qrc
index 9814208e..f302501b 100644
--- a/src/virtualkeyboard/content/content.qrc
+++ b/src/virtualkeyboard/content/content.qrc
@@ -17,6 +17,7 @@
<file>components/KeyboardLayout.qml</file>
<file>components/KeyboardLayoutLoader.qml</file>
<file>components/KeyboardRow.qml</file>
+ <file>components/ModeKey.qml</file>
<file>components/MultiSoundEffect.qml</file>
<file>components/MultitapInputMethod.qml</file>
<file>components/NumberKey.qml</file>
diff --git a/src/virtualkeyboard/content/layouts/zh_TW/main.qml b/src/virtualkeyboard/content/layouts/zh_TW/main.qml
new file mode 100644
index 00000000..784e2ec3
--- /dev/null
+++ b/src/virtualkeyboard/content/layouts/zh_TW/main.qml
@@ -0,0 +1,393 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd
+** All rights reserved.
+** For any questions to The Qt Company, please use contact form at http://qt.io
+**
+** This file is part of the Qt Virtual Keyboard module.
+**
+** Licensees holding valid commercial license for Qt may use this file in
+** accordance with the Qt License Agreement provided with the Software
+** or, alternatively, in accordance with the terms contained in a written
+** agreement between you and The Qt Company.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.io
+**
+******************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Layouts 1.0
+import QtQuick.Enterprise.VirtualKeyboard 2.0
+
+KeyboardLayoutLoader {
+ function createInputMethod() {
+ return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.Enterprise.VirtualKeyboard 2.0; TCInputMethod {}', parent, "tcInputMethod")
+ }
+ sharedLayouts: ['symbols']
+ sourceComponent: InputContext.shift ? pageLatin : pageCangjie
+ Component {
+ id: pageCangjie
+ KeyboardLayout {
+ keyWeight: 160
+ smallTextVisible: true
+ KeyboardRow {
+ Key {
+ text: "\u624B"
+ smallText: "q"
+ }
+ Key {
+ text: "\u7530"
+ smallText: "w"
+ }
+ Key {
+ text: "\u6C34"
+ smallText: "e"
+ }
+ Key {
+ text: "\u53E3"
+ smallText: "r"
+ }
+ Key {
+ text: "\u5EFF"
+ smallText: "t"
+ }
+ Key {
+ text: "\u535C"
+ smallText: "y"
+ }
+ Key {
+ text: "\u5C71"
+ smallText: "u"
+ }
+ Key {
+ text: "\u6208"
+ smallText: "i"
+ }
+ Key {
+ text: "\u4EBA"
+ smallText: "o"
+ }
+ Key {
+ text: "\u5FC3"
+ smallText: "p"
+ }
+ BackspaceKey {}
+ }
+ KeyboardRow {
+ FillerKey {
+ weight: 56
+ }
+ Key {
+ text: "\u65E5"
+ smallText: "a"
+ }
+ Key {
+ text: "\u5C38"
+ smallText: "s"
+ }
+ Key {
+ text: "\u6728"
+ smallText: "d"
+ }
+ Key {
+ text: "\u706B"
+ smallText: "f"
+ }
+ Key {
+ text: "\u571F"
+ smallText: "g"
+ }
+ Key {
+ text: "\u7AF9"
+ smallText: "h"
+ }
+ Key {
+ text: "\u5341"
+ smallText: "j"
+ }
+ Key {
+ text: "\u5927"
+ smallText: "k"
+ }
+ Key {
+ text: "\u4E2D"
+ smallText: "l"
+ }
+ EnterKey {
+ weight: 283
+ }
+ }
+ KeyboardRow {
+ keyWeight: 156
+ ModeKey {
+ id: simplifiedModeKey
+ key: Qt.Key_Mode_switch
+ displayText: "速成"
+ Component.onCompleted: updateBinding()
+ Connections {
+ target: InputContext.inputEngine
+ onInputMethodChanged: simplifiedModeKey.updateBinding()
+ }
+ function updateBinding() {
+ if (InputContext.inputEngine.inputMethod && InputContext.inputEngine.inputMethod.hasOwnProperty("simplified")) {
+ simplifiedModeKey.mode = InputContext.inputEngine.inputMethod.simplified
+ InputContext.inputEngine.inputMethod.simplified = Qt.binding(function() { return simplifiedModeKey.mode })
+ }
+ }
+ }
+ Key {
+ text: "\u91CD"
+ smallText: "z"
+ }
+ Key {
+ text: "\u96E3"
+ smallText: "x"
+ }
+ Key {
+ text: "\u91D1"
+ smallText: "c"
+ }
+ Key {
+ text: "\u5973"
+ smallText: "v"
+ }
+ Key {
+ text: "\u6708"
+ smallText: "b"
+ }
+ Key {
+ text: "\u5F13"
+ smallText: "n"
+ }
+ Key {
+ text: "\u4E00"
+ smallText: "m"
+ }
+ Key {
+ key: Qt.Key_Comma
+ text: "\uFF0C"
+ alternativeKeys: "\uFF0C\uFF1B\u3001"
+ }
+ Key {
+ key: Qt.Key_Period
+ text: "\uFF0E"
+ alternativeKeys: "\uFF0E\uFF1A\u3002"
+ }
+ ShiftKey {
+ weight: 204
+ }
+ }
+ KeyboardRow {
+ keyWeight: 154
+ SymbolModeKey {
+ weight: 217
+ }
+ ChangeLanguageKey {
+ weight: 154
+ }
+ SpaceKey {
+ weight: 864
+ }
+ Key {
+ key: Qt.Key_Question
+ text: "\uFF1F"
+ alternativeKeys: "\uFF1F\uFF01"
+ }
+ Key {
+ key: 0xE000
+ text: ":-)"
+ smallTextVisible: false
+ alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ]
+ }
+ HideKeyboardKey {
+ weight: 204
+ }
+ }
+ }
+ }
+ Component {
+ id: pageLatin
+ KeyboardLayout {
+ keyWeight: 160
+ smallTextVisible: true
+ KeyboardRow {
+ Key {
+ key: Qt.Key_Q
+ text: "q"
+ }
+ Key {
+ key: Qt.Key_W
+ text: "w"
+ }
+ Key {
+ key: Qt.Key_E
+ text: "e"
+ }
+ Key {
+ key: Qt.Key_R
+ text: "r"
+ }
+ Key {
+ key: Qt.Key_T
+ text: "t"
+ }
+ Key {
+ key: Qt.Key_Y
+ text: "y"
+ }
+ Key {
+ key: Qt.Key_U
+ text: "u"
+ }
+ Key {
+ key: Qt.Key_I
+ text: "i"
+ }
+ Key {
+ key: Qt.Key_O
+ text: "o"
+ }
+ Key {
+ key: Qt.Key_P
+ text: "p"
+ }
+ BackspaceKey {}
+ }
+ KeyboardRow {
+ FillerKey {
+ weight: 56
+ }
+ Key {
+ key: Qt.Key_A
+ text: "a"
+ }
+ Key {
+ key: Qt.Key_S
+ text: "s"
+ }
+ Key {
+ key: Qt.Key_D
+ text: "d"
+ }
+ Key {
+ key: Qt.Key_F
+ text: "f"
+ }
+ Key {
+ key: Qt.Key_G
+ text: "g"
+ }
+ Key {
+ key: Qt.Key_H
+ text: "h"
+ }
+ Key {
+ key: Qt.Key_J
+ text: "j"
+ }
+ Key {
+ key: Qt.Key_K
+ text: "k"
+ }
+ Key {
+ key: Qt.Key_L
+ text: "l"
+ }
+ EnterKey {
+ weight: 283
+ }
+ }
+ KeyboardRow {
+ keyWeight: 156
+ ModeKey {
+ id: simplifiedModeKey
+ key: Qt.Key_Mode_switch
+ enabled: InputContext.inputEngine.inputMode == InputEngine.Cangjie
+ displayText: "速成"
+ Component.onCompleted: updateBinding()
+ Connections {
+ target: InputContext.inputEngine
+ onInputMethodChanged: simplifiedModeKey.updateBinding()
+ }
+ function updateBinding() {
+ if (InputContext.inputEngine.inputMethod && InputContext.inputEngine.inputMethod.hasOwnProperty("simplified")) {
+ simplifiedModeKey.mode = InputContext.inputEngine.inputMethod.simplified
+ InputContext.inputEngine.inputMethod.simplified = Qt.binding(function() { return simplifiedModeKey.mode })
+ }
+ }
+ }
+ Key {
+ key: Qt.Key_Z
+ text: "z"
+ }
+ Key {
+ key: Qt.Key_X
+ text: "x"
+ }
+ Key {
+ key: Qt.Key_C
+ text: "c"
+ }
+ Key {
+ key: Qt.Key_V
+ text: "v"
+ }
+ Key {
+ key: Qt.Key_B
+ text: "b"
+ }
+ Key {
+ key: Qt.Key_N
+ text: "n"
+ }
+ Key {
+ key: Qt.Key_M
+ text: "m"
+ }
+ Key {
+ key: Qt.Key_Comma
+ text: "\uFF0C"
+ alternativeKeys: "\uFF0C\uFF1B\u3001"
+ }
+ Key {
+ key: Qt.Key_Period
+ text: "\uFF0E"
+ alternativeKeys: "\uFF0E\uFF1A\u3002"
+ }
+ ShiftKey {
+ weight: 204
+ }
+ }
+ KeyboardRow {
+ keyWeight: 154
+ SymbolModeKey {
+ weight: 217
+ }
+ ChangeLanguageKey {
+ weight: 154
+ }
+ HandwritingModeKey {
+ weight: 154
+ }
+ SpaceKey {
+ weight: 864
+ }
+ Key {
+ key: Qt.Key_Question
+ text: "\uFF1F"
+ alternativeKeys: "\uFF1F\uFF01"
+ }
+ Key {
+ key: 0xE000
+ text: ":-)"
+ smallTextVisible: false
+ alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ]
+ }
+ HideKeyboardKey {
+ weight: 204
+ }
+ }
+ }
+ }
+}
diff --git a/src/virtualkeyboard/content/layouts/zh_TW/symbols.qml b/src/virtualkeyboard/content/layouts/zh_TW/symbols.qml
new file mode 100644
index 00000000..72757e85
--- /dev/null
+++ b/src/virtualkeyboard/content/layouts/zh_TW/symbols.qml
@@ -0,0 +1,283 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd
+** All rights reserved.
+** For any questions to The Qt Company, please use contact form at http://qt.io
+**
+** This file is part of the Qt Virtual Keyboard module.
+**
+** Licensees holding valid commercial license for Qt may use this file in
+** accordance with the Qt License Agreement provided with the Software
+** or, alternatively, in accordance with the terms contained in a written
+** agreement between you and The Qt Company.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.io
+**
+******************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Layouts 1.0
+import QtQuick.Enterprise.VirtualKeyboard 2.0
+
+KeyboardLayoutLoader {
+ function createInputMethod() {
+ return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.Enterprise.VirtualKeyboard 2.0; TCInputMethod {}', parent, "tcInputMethod")
+ }
+ sharedLayouts: ['main']
+ property int page
+ readonly property int numPages: 3
+ property var keysPage1: [
+ "1234567890",
+ "@#$%^&*()",
+ "“”、=:;!?~"
+ ]
+ property var keysPage2: [
+ "-+/\\|[]{}·",
+ "<>,.:;!?~",
+ "/\"'_§¥€£¢"
+ ]
+ property var keysPage3: [
+ "()〔〕〈〉《》【】",
+ "→←↑↓↔■□●○",
+ "\『』「」★☆◆◇"
+ ]
+ sourceComponent: {
+ switch (page) {
+ case 2: return page3
+ case 1: return page2
+ default: return page1
+ }
+ }
+ Component {
+ id: page1
+ KeyboardLayout {
+ keyWeight: 160
+ KeyboardRow {
+ Repeater {
+ model: keysPage1[0].length
+ Key {
+ key: keysPage1[0][index].charCodeAt(0)
+ text: keysPage1[0][index]
+ }
+ }
+ BackspaceKey {}
+ }
+ KeyboardRow {
+ FillerKey {
+ weight: 56
+ }
+ Repeater {
+ model: keysPage1[1].length
+ Key {
+ key: keysPage1[1][index].charCodeAt(0)
+ text: keysPage1[1][index]
+ }
+ }
+ EnterKey {
+ weight: 283
+ }
+ }
+ KeyboardRow {
+ keyWeight: 156
+ Key {
+ displayText: (page + 1) + "/" + numPages
+ functionKey: true
+ onClicked: page = (page + 1) % numPages
+ }
+ Repeater {
+ model: keysPage1[2].length
+ Key {
+ key: keysPage1[2][index].charCodeAt(0)
+ text: keysPage1[2][index]
+ }
+ }
+ Key {
+ weight: 204
+ displayText: (page + 1) + "/" + numPages
+ functionKey: true
+ onClicked: page = (page + 1) % numPages
+ }
+ }
+ KeyboardRow {
+ keyWeight: 154
+ SymbolModeKey {
+ weight: 217
+ displayText: "ABC"
+ }
+ ChangeLanguageKey {
+ weight: 154
+ }
+ SpaceKey {
+ weight: 864
+ }
+ Key {
+ key: 0x2014
+ text: "—"
+ }
+ Key {
+ key: 0xE000
+ text: ":-)"
+ alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ]
+ }
+ HideKeyboardKey {
+ weight: 204
+ }
+ }
+ }
+ }
+ Component {
+ id: page2
+ KeyboardLayout {
+ keyWeight: 160
+ KeyboardRow {
+ Repeater {
+ model: keysPage2[0].length
+ Key {
+ key: keysPage2[0][index].charCodeAt(0)
+ text: keysPage2[0][index]
+ }
+ }
+ BackspaceKey {}
+ }
+ KeyboardRow {
+ FillerKey {
+ weight: 56
+ }
+ Repeater {
+ model: keysPage2[1].length
+ Key {
+ key: keysPage2[1][index].charCodeAt(0)
+ text: keysPage2[1][index]
+ }
+ }
+ EnterKey {
+ weight: 283
+ }
+ }
+ KeyboardRow {
+ keyWeight: 156
+ Key {
+ displayText: (page + 1) + "/" + numPages
+ functionKey: true
+ onClicked: page = (page + 1) % numPages
+ }
+ Repeater {
+ model: keysPage2[2].length
+ Key {
+ key: keysPage2[2][index].charCodeAt(0)
+ text: keysPage2[2][index]
+ }
+ }
+ Key {
+ weight: 204
+ displayText: (page + 1) + "/" + numPages
+ functionKey: true
+ onClicked: page = (page + 1) % numPages
+ }
+ }
+ KeyboardRow {
+ keyWeight: 154
+ SymbolModeKey {
+ weight: 217
+ displayText: "ABC"
+ }
+ ChangeLanguageKey {
+ weight: 154
+ }
+ SpaceKey {
+ weight: 864
+ }
+ Key {
+ key: 0x3002
+ text: "。"
+ }
+ Key {
+ key: 0xE000
+ text: ":-)"
+ alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ]
+ }
+ HideKeyboardKey {
+ weight: 204
+ }
+ }
+ }
+ }
+ Component {
+ id: page3
+ KeyboardLayout {
+ keyWeight: 160
+ KeyboardRow {
+ Repeater {
+ model: keysPage3[0].length
+ Key {
+ key: keysPage3[0][index].charCodeAt(0)
+ text: keysPage3[0][index]
+ }
+ }
+ BackspaceKey {}
+ }
+ KeyboardRow {
+ FillerKey {
+ weight: 56
+ }
+ Repeater {
+ model: keysPage3[1].length
+ Key {
+ key: keysPage3[1][index].charCodeAt(0)
+ text: keysPage3[1][index]
+ }
+ }
+ EnterKey {
+ weight: 283
+ }
+ }
+ KeyboardRow {
+ keyWeight: 156
+ Key {
+ displayText: (page + 1) + "/" + numPages
+ functionKey: true
+ onClicked: page = (page + 1) % numPages
+ }
+ Repeater {
+ model: keysPage3[2].length
+ Key {
+ key: keysPage3[2][index].charCodeAt(0)
+ text: keysPage3[2][index]
+ }
+ }
+ Key {
+ weight: 204
+ displayText: (page + 1) + "/" + numPages
+ functionKey: true
+ onClicked: page = (page + 1) % numPages
+ }
+ }
+ KeyboardRow {
+ keyWeight: 154
+ SymbolModeKey {
+ weight: 217
+ displayText: "ABC"
+ }
+ ChangeLanguageKey {
+ weight: 154
+ }
+ SpaceKey {
+ weight: 864
+ }
+ Key {
+ key: 0x2026
+ text: "…"
+ }
+ Key {
+ key: 0xE000
+ text: ":-)"
+ alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ]
+ }
+ HideKeyboardKey {
+ weight: 204
+ }
+ }
+ }
+ }
+}
diff --git a/src/virtualkeyboard/content/layouts_traditional_chinese.qrc b/src/virtualkeyboard/content/layouts_traditional_chinese.qrc
new file mode 100644
index 00000000..6850cf84
--- /dev/null
+++ b/src/virtualkeyboard/content/layouts_traditional_chinese.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/content">
+ <file>layouts/zh_TW/main.qml</file>
+ <file>layouts/zh_TW/symbols.qml</file>
+ <file>layouts/en_GB/dialpad.qml</file>
+ <file>layouts/en_GB/digits.qml</file>
+ <file>layouts/en_GB/handwriting.qml</file>
+ <file>layouts/en_GB/main.qml</file>
+ <file>layouts/en_GB/numbers.qml</file>
+ <file>layouts/en_GB/symbols.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/virtualkeyboard/content/styles/default/style.qml b/src/virtualkeyboard/content/styles/default/style.qml
index 4c2a653e..a3e47da9 100644
--- a/src/virtualkeyboard/content/styles/default/style.qml
+++ b/src/virtualkeyboard/content/styles/default/style.qml
@@ -25,7 +25,7 @@ import QtQuick.Enterprise.VirtualKeyboard.Styles 2.0
KeyboardStyle {
id: currentStyle
- readonly property bool pinyinMode: InputContext.inputEngine.inputMode === InputEngine.Pinyin
+ readonly property bool compactSelectionList: [InputEngine.Pinyin, InputEngine.Cangjie].indexOf(InputContext.inputEngine.inputMode) !== -1
readonly property string fontFamily: "Sans"
readonly property real keyBackgroundMargin: Math.round(13 * scaleHint)
readonly property real keyContentMargin: Math.round(45 * scaleHint)
@@ -508,6 +508,70 @@ KeyboardStyle {
]
}
+ modeKeyPanel: KeyPanel {
+ Rectangle {
+ id: modeKeyBackground
+ radius: 5
+ color: "#1e1b18"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Text {
+ id: modeKeyText
+ text: control.displayText
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.fill: parent
+ anchors.margins: keyContentMargin
+ font {
+ family: fontFamily
+ weight: Font.Normal
+ pixelSize: 44 * scaleHint
+ capitalization: Font.AllUppercase
+ }
+ }
+ Rectangle {
+ id: modeKeyIndicator
+ implicitHeight: parent.height * 0.1
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: parent.width * 0.4
+ anchors.rightMargin: parent.width * 0.4
+ anchors.bottomMargin: parent.height * 0.12
+ color: "#80c342"
+ radius: 3
+ visible: control.mode
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: modeKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: modeKeyText
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: modeKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: modeKeyText
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
handwritingKeyPanel: KeyPanel {
Rectangle {
id: hwrKeyBackground
@@ -622,7 +686,7 @@ KeyboardStyle {
Text {
id: selectionListLabel
anchors.left: parent.left
- anchors.leftMargin: Math.round((pinyinMode ? 50 : 140) * scaleHint)
+ anchors.leftMargin: Math.round((compactSelectionList ? 50 : 140) * scaleHint)
anchors.verticalCenter: parent.verticalCenter
text: decorateText(display, wordCompletionLength)
color: "#80c342"
diff --git a/src/virtualkeyboard/content/styles/retro/style.qml b/src/virtualkeyboard/content/styles/retro/style.qml
index 5c454fae..08680bd2 100644
--- a/src/virtualkeyboard/content/styles/retro/style.qml
+++ b/src/virtualkeyboard/content/styles/retro/style.qml
@@ -25,7 +25,7 @@ import QtQuick.Enterprise.VirtualKeyboard.Styles 2.0
KeyboardStyle {
id: currentStyle
- readonly property bool pinyinMode: InputContext.inputEngine.inputMode === InputEngine.Pinyin
+ readonly property bool compactSelectionList: [InputEngine.Pinyin, InputEngine.Cangjie].indexOf(InputContext.inputEngine.inputMode) !== -1
readonly property string fontFamily: "Courier"
readonly property real keyBackgroundMargin: Math.round(9 * scaleHint)
readonly property real keyContentMargin: Math.round(50 * scaleHint)
@@ -564,6 +564,63 @@ KeyboardStyle {
]
}
+ modeKeyPanel: KeyPanel {
+ BorderImage {
+ id: modeKeyBackground
+ source: resourcePrefix + "images/key154px_black.png"
+ width: (parent.width - 2 * keyBackgroundMargin) / scale
+ height: sourceSize.height
+ anchors.centerIn: parent
+ border.left: 76
+ border.top: 76
+ border.right: 76
+ border.bottom: 76
+ horizontalTileMode: BorderImage.Stretch
+ scale: (parent.height - 2 * keyBackgroundMargin) / sourceSize.height
+ states: [
+ State {
+ name: "mode"
+ when: control.mode
+ PropertyChanges {
+ target: modeKeyBackground
+ source: resourcePrefix + "images/key154px_capslock.png"
+ }
+ }
+ ]
+ }
+ Text {
+ id: modeKeyText
+ text: control.displayText
+ color: "#c5a96f"
+ anchors.centerIn: parent
+ font {
+ family: fontFamily
+ weight: Font.DemiBold
+ pixelSize: 74 * scaleHint
+ letterSpacing: -5 * scaleHint
+ capitalization: Font.AllUppercase
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: modeKeyBackground
+ opacity: 0.70
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: modeKeyBackground
+ opacity: 0.20
+ }
+ }
+ ]
+ }
+
handwritingKeyPanel: KeyPanel {
BorderImage {
id: hwrKeyBackground
@@ -728,7 +785,7 @@ KeyboardStyle {
Text {
id: selectionListLabel
anchors.left: parent.left
- anchors.leftMargin: Math.round((pinyinMode ? 50 : 140) * scaleHint)
+ anchors.leftMargin: Math.round((compactSelectionList ? 50 : 140) * scaleHint)
anchors.verticalCenter: parent.verticalCenter
text: decorateText(display, wordCompletionLength)
color: "white"
diff --git a/src/virtualkeyboard/declarativeinputengine.cpp b/src/virtualkeyboard/declarativeinputengine.cpp
index 9fd54b25..aa153fb6 100644
--- a/src/virtualkeyboard/declarativeinputengine.cpp
+++ b/src/virtualkeyboard/declarativeinputengine.cpp
@@ -706,6 +706,7 @@ void DeclarativeInputEngine::timerEvent(QTimerEvent *timerEvent)
\li \c InputEngine.Numeric Only numeric input is allowed.
\li \c InputEngine.Dialable Only dialable input is allowed.
\li \c InputEngine.Pinyin Pinyin input mode for Chinese.
+ \li \c InputEngine.Cangjie Cangjie input mode for Chinese.
\li \c InputEngine.Hangul Hangul input mode for Korean.
\li \c InputEngine.Hiragana Hiragana input mode for Japanese.
\li \c InputEngine.Katakana Katakana input mode for Japanese.
@@ -765,6 +766,8 @@ void DeclarativeInputEngine::timerEvent(QTimerEvent *timerEvent)
Only dialable input is allowed.
\value Pinyin
Pinyin input mode for Chinese.
+ \value Cangjie
+ Cangjie input mode for Chinese.
\value Hangul
Hangul input mode for Korean.
\value Hiragana
diff --git a/src/virtualkeyboard/declarativeinputengine.h b/src/virtualkeyboard/declarativeinputengine.h
index 99cbf646..fafc64f3 100644
--- a/src/virtualkeyboard/declarativeinputengine.h
+++ b/src/virtualkeyboard/declarativeinputengine.h
@@ -61,6 +61,7 @@ public:
Numeric,
Dialable,
Pinyin,
+ Cangjie,
Hangul,
Hiragana,
Katakana,
diff --git a/src/virtualkeyboard/declarativeshifthandler.cpp b/src/virtualkeyboard/declarativeshifthandler.cpp
index 904d7bf4..53c44d49 100644
--- a/src/virtualkeyboard/declarativeshifthandler.cpp
+++ b/src/virtualkeyboard/declarativeshifthandler.cpp
@@ -36,7 +36,8 @@ public:
toggleShiftEnabled(false),
shiftChanged(false),
manualShiftLanguageFilter(QSet<QLocale::Language>() << QLocale::Arabic << QLocale::Persian << QLocale::Hindi << QLocale::Korean),
- noAutoUppercaseInputModeFilter(QSet<DeclarativeInputEngine::InputMode>() << DeclarativeInputEngine::FullwidthLatin),
+ manualCapsInputModeFilter(QSet<DeclarativeInputEngine::InputMode>() << DeclarativeInputEngine::Cangjie),
+ noAutoUppercaseInputModeFilter(QSet<DeclarativeInputEngine::InputMode>() << DeclarativeInputEngine::FullwidthLatin << DeclarativeInputEngine::Pinyin << DeclarativeInputEngine::Cangjie),
allCapsInputModeFilter(QSet<DeclarativeInputEngine::InputMode>() << DeclarativeInputEngine::Hiragana << DeclarativeInputEngine::Katakana)
{
}
@@ -48,6 +49,7 @@ public:
bool shiftChanged;
QLocale locale;
const QSet<QLocale::Language> manualShiftLanguageFilter;
+ const QSet<DeclarativeInputEngine::InputMode> manualCapsInputModeFilter;
const QSet<DeclarativeInputEngine::InputMode> noAutoUppercaseInputModeFilter;
const QSet<DeclarativeInputEngine::InputMode> allCapsInputModeFilter;
};
@@ -149,7 +151,8 @@ void DeclarativeShiftHandler::toggleShift()
if (d->manualShiftLanguageFilter.contains(d->locale.language())) {
d->inputContext->setCapsLock(false);
d->inputContext->setShift(!d->inputContext->shift());
- } else if (d->inputContext->inputMethodHints() & Qt::ImhNoAutoUppercase) {
+ } else if (d->inputContext->inputMethodHints() & Qt::ImhNoAutoUppercase ||
+ d->manualCapsInputModeFilter.contains(d->inputContext->inputEngine()->inputMode())) {
bool capsLock = d->inputContext->capsLock();
d->inputContext->setCapsLock(!capsLock);
d->inputContext->setShift(!capsLock);
@@ -174,7 +177,8 @@ void DeclarativeShiftHandler::reset()
bool toggleShiftEnabled = !(inputMethodHints & (Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly));
// For filtered languages reset the initial shift status to lower case
// and allow manual shift change
- if (d->manualShiftLanguageFilter.contains(d->locale.language())) {
+ if (d->manualShiftLanguageFilter.contains(d->locale.language()) ||
+ d->manualCapsInputModeFilter.contains(inputMode)) {
preferUpperCase = false;
autoCapitalizationEnabled = false;
toggleShiftEnabled = true;
diff --git a/src/virtualkeyboard/doc/src/build.qdoc b/src/virtualkeyboard/doc/src/build.qdoc
index e314631c..a5c8c6a2 100644
--- a/src/virtualkeyboard/doc/src/build.qdoc
+++ b/src/virtualkeyboard/doc/src/build.qdoc
@@ -52,6 +52,9 @@ The project is split into the following subprojects:
\row
\li \e src/virtualkeyboard/3rdparty/pinyin/pinyin.pro
\li A project file for compiling the PinyinIME library.
+\row
+ \li \e src/virtualkeyboard/3rdparty/tcime/tcime.pro
+ \li A project file for compiling the TCIME library.
\endtable
The input methods are implemented either in C++ or QML.
@@ -106,6 +109,11 @@ build targets.
\li This option activates the Pinyin input method for the Simplified Chinese
language and disables all other default languages, except English.
\row
+ \li \e tcime
+ \li Enables the Cangjie input method for Traditional Chinese.
+ \li This option activates the Canjie input method for the Traditional Chinese
+ language and disables all other default languages, except English.
+\row
\li \e hangul
\li Enables the Hangul input method for Korean.
\li This option activates the Hangul input method for the Korean
diff --git a/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc b/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc
index 55a9db45..20d8b29c 100644
--- a/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc
+++ b/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc
@@ -40,7 +40,7 @@
\li Character preview and alternative character view.
\li Automatic capitalization and space insertion.
\li Scalability to different resolutions.
- \li Support for different character sets (Latin, Simplified Chinese,
+ \li Support for different character sets (Latin, Simplified/Traditional Chinese,
Hindi, Japanese, Arabic, Korean, and others).
\li Support for most common input \l {Supported Languages}{languages},
with possibility to easily extend the language support.
@@ -72,6 +72,7 @@
\li Portugese
\li Russian
\li Simplified Chinese
+ \li Traditional Chinese
\li Spanish
\li Swedish
\endlist
diff --git a/src/virtualkeyboard/plugin.cpp b/src/virtualkeyboard/plugin.cpp
index a1599e85..bbd83131 100644
--- a/src/virtualkeyboard/plugin.cpp
+++ b/src/virtualkeyboard/plugin.cpp
@@ -30,6 +30,9 @@
#ifdef HAVE_PINYIN
#include "pinyininputmethod.h"
#endif
+#ifdef HAVE_TCIME
+#include "tcinputmethod.h"
+#endif
#ifdef HAVE_HANGUL
#include "hangulinputmethod.h"
#endif
@@ -67,6 +70,9 @@ static QObject *createInputContextModule(QQmlEngine *engine, QJSEngine *scriptEn
#ifdef HAVE_PINYIN
<< QLatin1String("PinyinInputMethod")
#endif
+#ifdef HAVE_TCIME
+ << QLatin1String("TCInputMethod")
+#endif
#ifdef HAVE_HANGUL
<< QLatin1String("HangulInputMethod")
#endif
@@ -121,6 +127,9 @@ QPlatformInputContext *PlatformInputContextPlugin::create(const QString &system,
qmlRegisterType<PinyinInputMethod>(pluginUri, 1, 1, "PinyinInputMethod");
qmlRegisterType<PinyinInputMethod>(pluginUri, 2, 0, "PinyinInputMethod");
#endif
+#ifdef HAVE_TCIME
+ qmlRegisterType<TCInputMethod>(pluginUri, 2, 0, "TCInputMethod");
+#endif
#ifdef HAVE_HANGUL
qmlRegisterType<HangulInputMethod>(pluginUri, 1, 3, "HangulInputMethod");
qmlRegisterType<HangulInputMethod>(pluginUri, 2, 0, "HangulInputMethod");
@@ -180,6 +189,7 @@ QPlatformInputContext *PlatformInputContextPlugin::create(const QString &system,
qmlRegisterType(QUrl(componentsPath + QLatin1String("KeyboardRow.qml")), pluginUri, 2, 0, "KeyboardRow");
qmlRegisterType(QUrl(componentsPath + QLatin1String("Key.qml")), pluginUri, 1, 0, "Key");
qmlRegisterType(QUrl(componentsPath + QLatin1String("Key.qml")), pluginUri, 2, 0, "Key");
+ qmlRegisterType(QUrl(componentsPath + QLatin1String("ModeKey.qml")), pluginUri, 2, 0, "ModeKey");
qmlRegisterType(QUrl(componentsPath + QLatin1String("MultiSoundEffect.qml")), pluginUri, 1, 1, "MultiSoundEffect");
qmlRegisterType(QUrl(componentsPath + QLatin1String("MultiSoundEffect.qml")), pluginUri, 2, 0, "MultiSoundEffect");
qmlRegisterType(QUrl(componentsPath + QLatin1String("MultitapInputMethod.qml")), pluginUri, 1, 0, "MultitapInputMethod");
diff --git a/src/virtualkeyboard/styles/KeyboardStyle.qml b/src/virtualkeyboard/styles/KeyboardStyle.qml
index 541091fa..50add72b 100644
--- a/src/virtualkeyboard/styles/KeyboardStyle.qml
+++ b/src/virtualkeyboard/styles/KeyboardStyle.qml
@@ -155,6 +155,18 @@ QtObject {
*/
property Component symbolKeyPanel: null
+ /*! Template for the generic mode key.
+
+ This template provides a visualization of the key in which the state
+ can be on / off. This template is used in situations where the key label
+ will remain the same regardless of status.
+
+ The current state is available in the \c control.mode property.
+
+ \note The delegate must be based on the KeyPanel type.
+ */
+ property Component modeKeyPanel: null
+
/*! Template for the handwriting mode key.
\note The delegate must be based on the KeyPanel type.
diff --git a/src/virtualkeyboard/tcinputmethod.cpp b/src/virtualkeyboard/tcinputmethod.cpp
new file mode 100644
index 00000000..a37161b1
--- /dev/null
+++ b/src/virtualkeyboard/tcinputmethod.cpp
@@ -0,0 +1,330 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd
+** All rights reserved.
+** For any questions to The Qt Company, please use contact form at http://qt.io
+**
+** This file is part of the Qt Virtual Keyboard module.
+**
+** Licensees holding valid commercial license for Qt may use this file in
+** accordance with the Qt License Agreement provided with the Software
+** or, alternatively, in accordance with the terms contained in a written
+** agreement between you and The Qt Company.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.io
+**
+******************************************************************************/
+
+#include "tcinputmethod.h"
+#include "declarativeinputengine.h"
+#include "declarativeinputcontext.h"
+#include "cangjiedictionary.h"
+#include "cangjietable.h"
+#include "phrasedictionary.h"
+#include "virtualkeyboarddebug.h"
+
+#include <QLibraryInfo>
+
+using namespace tcime;
+
+class TCInputMethodPrivate : public AbstractInputMethodPrivate
+{
+ Q_DECLARE_PUBLIC(TCInputMethod)
+public:
+
+ TCInputMethodPrivate(TCInputMethod *q_ptr) :
+ AbstractInputMethodPrivate(),
+ q_ptr(q_ptr),
+ highlightIndex(-1)
+ {}
+
+ bool setCandidates(const QStringList &values, bool highlightDefault)
+ {
+ bool candidatesChanged = candidates != values;
+ candidates = values;
+ highlightIndex = !candidates.isEmpty() && highlightDefault ? 0 : -1;
+ return candidatesChanged;
+ }
+
+ bool clearCandidates()
+ {
+ if (candidates.isEmpty())
+ return false;
+
+ candidates.clear();
+ highlightIndex = -1;
+ return true;
+ }
+
+ QString pickHighlighted() const
+ {
+ return (highlightIndex >= 0 && highlightIndex < candidates.count()) ? candidates[highlightIndex] : QString();
+ }
+
+ void reset()
+ {
+ if (clearCandidates()) {
+ Q_Q(TCInputMethod);
+ emit q->selectionListChanged(DeclarativeSelectionListModel::WordCandidateList);
+ emit q->selectionListActiveItemChanged(DeclarativeSelectionListModel::WordCandidateList, highlightIndex);
+ }
+ input.clear();
+ }
+
+ bool checkSpecialCharInput()
+ {
+ if (input.length() == 1 && input.at(0).unicode() == 0x91CD) {
+ static const QStringList specialChars1 = QStringList()
+ << QChar(0xFF01) << QChar(0x2018) << QChar(0x3000) << QChar(0xFF0C)
+ << QChar(0x3001) << QChar(0x3002) << QChar(0xFF0E) << QChar(0xFF1B)
+ << QChar(0xFF1A) << QChar(0xFF1F) << QChar(0x300E) << QChar(0x300F)
+ << QChar(0x3010) << QChar(0x3011) << QChar(0xFE57) << QChar(0x2026)
+ << QChar(0x2025) << QChar(0xFE50) << QChar(0xFE51) << QChar(0xFE52)
+ << QChar(0x00B7) << QChar(0xFE54) << QChar(0x2574) << QChar(0x2027)
+ << QChar(0x2032) << QChar(0x2035) << QChar(0x301E) << QChar(0x301D)
+ << QChar(0x201D) << QChar(0x201C) << QChar(0x2019) << QChar(0xFE55)
+ << QChar(0xFE5D) << QChar(0xFE5E) << QChar(0xFE59) << QChar(0xFE5A)
+ << QChar(0xFE5B) << QChar(0xFE5C) << QChar(0xFE43) << QChar(0xFE44);
+ Q_Q(TCInputMethod);
+ if (setCandidates(specialChars1, true)) {
+ emit q->selectionListChanged(DeclarativeSelectionListModel::WordCandidateList);
+ emit q->selectionListActiveItemChanged(DeclarativeSelectionListModel::WordCandidateList, highlightIndex);
+ }
+ q->inputContext()->setPreeditText(candidates[highlightIndex]);
+ return true;
+ } else if (input.length() == 2 && input.at(0).unicode() == 0x91CD && input.at(1).unicode() == 0x96E3) {
+ static const QStringList specialChars2 = QStringList()
+ << QChar(0x3008) << QChar(0x3009) << QChar(0xFE31) << QChar(0x2013)
+ << QChar(0xFF5C) << QChar(0x300C) << QChar(0x300D) << QChar(0xFE40)
+ << QChar(0xFE3F) << QChar(0x2014) << QChar(0xFE3E) << QChar(0xFE3D)
+ << QChar(0x300A) << QChar(0x300B) << QChar(0xFE3B) << QChar(0xFE3C)
+ << QChar(0xFE56) << QChar(0xFE30) << QChar(0xFE39) << QChar(0xFE3A)
+ << QChar(0x3014) << QChar(0x3015) << QChar(0xFE37) << QChar(0xFE38)
+ << QChar(0xFE41) << QChar(0xFE42) << QChar(0xFF5B) << QChar(0xFF5D)
+ << QChar(0xFE35) << QChar(0xFE36) << QChar(0xFF08) << QChar(0xFF09)
+ << QChar(0xFE4F) << QChar(0xFE34) << QChar(0xFE33);
+ Q_Q(TCInputMethod);
+ if (setCandidates(specialChars2, true)) {
+ emit q->selectionListChanged(DeclarativeSelectionListModel::WordCandidateList);
+ emit q->selectionListActiveItemChanged(DeclarativeSelectionListModel::WordCandidateList, highlightIndex);
+ }
+ q->inputContext()->setPreeditText(candidates[highlightIndex]);
+ return true;
+ }
+ return false;
+ }
+
+ TCInputMethod *q_ptr;
+ CangjieDictionary cangjieDictionary;
+ PhraseDictionary phraseDictionary;
+ QString input;
+ QStringList candidates;
+ int highlightIndex;
+};
+
+TCInputMethod::TCInputMethod(QObject *parent) :
+ AbstractInputMethod(*new TCInputMethodPrivate(this), parent)
+{
+}
+
+TCInputMethod::~TCInputMethod()
+{
+}
+
+bool TCInputMethod::simplified() const
+{
+ Q_D(const TCInputMethod);
+ return d->cangjieDictionary.simplified();
+}
+
+void TCInputMethod::setSimplified(bool simplified)
+{
+ Q_D(TCInputMethod);
+ VIRTUALKEYBOARD_DEBUG() << "TCInputMethod::setSimplified(): " << simplified;
+ if (d->cangjieDictionary.simplified() != simplified) {
+ d->reset();
+ DeclarativeInputContext *ic = inputContext();
+ if (ic)
+ ic->clear();
+ d->cangjieDictionary.setSimplified(simplified);
+ emit simplifiedChanged();
+ }
+}
+
+QList<DeclarativeInputEngine::InputMode> TCInputMethod::inputModes(const QString &locale)
+{
+ Q_UNUSED(locale)
+ return QList<DeclarativeInputEngine::InputMode>()
+ << DeclarativeInputEngine::Cangjie;
+}
+
+bool TCInputMethod::setInputMode(const QString &locale, DeclarativeInputEngine::InputMode inputMode)
+{
+ Q_UNUSED(locale)
+ Q_UNUSED(inputMode)
+ Q_D(TCInputMethod);
+ if (inputMode == DeclarativeInputEngine::Cangjie) {
+ if (d->cangjieDictionary.isEmpty()) {
+ QString cangjieDictionary(QString::fromLatin1(qgetenv("QT_VIRTUALKEYBOARD_CANGJIE_DICTIONARY").constData()));
+ if (cangjieDictionary.isEmpty())
+ cangjieDictionary = QLibraryInfo::location(QLibraryInfo::DataPath) + "/qtvirtualkeyboard/tcime/dict_cangjie.dat";
+ d->cangjieDictionary.load(cangjieDictionary);
+ }
+ if (d->phraseDictionary.isEmpty()) {
+ QString phraseDictionary(QString::fromLatin1(qgetenv("QT_VIRTUALKEYBOARD_PHRASE_DICTIONARY").constData()));
+ if (phraseDictionary.isEmpty())
+ phraseDictionary = QLibraryInfo::location(QLibraryInfo::DataPath) + "/qtvirtualkeyboard/tcime/dict_phrases.dat";
+ d->phraseDictionary.load(phraseDictionary);
+ }
+ return d->cangjieDictionary.isEmpty();
+ }
+ return false;
+}
+
+bool TCInputMethod::setTextCase(DeclarativeInputEngine::TextCase textCase)
+{
+ Q_UNUSED(textCase)
+ return true;
+}
+
+bool TCInputMethod::keyEvent(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers)
+{
+ Q_UNUSED(key)
+ Q_UNUSED(text)
+ Q_UNUSED(modifiers)
+ Q_D(TCInputMethod);
+ DeclarativeInputContext *ic = inputContext();
+ bool accept = false;
+ switch (key) {
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ update();
+ break;
+
+ case Qt::Key_Tab:
+ case Qt::Key_Space:
+ if (!d->input.isEmpty()) {
+ accept = true;
+ if (d->highlightIndex >= 0)
+ update();
+ } else {
+ update();
+ }
+ break;
+
+ case Qt::Key_Backspace:
+ if (!d->input.isEmpty()) {
+ d->input.remove(d->input.length() - 1, 1);
+ ic->setPreeditText(d->input);
+ if (!d->checkSpecialCharInput()) {
+ if (d->setCandidates(d->cangjieDictionary.getWords(d->input), true)) {
+ emit selectionListChanged(DeclarativeSelectionListModel::WordCandidateList);
+ emit selectionListActiveItemChanged(DeclarativeSelectionListModel::WordCandidateList, d->highlightIndex);
+ }
+ }
+ accept = true;
+ } else if (d->clearCandidates()) {
+ emit selectionListChanged(DeclarativeSelectionListModel::WordCandidateList);
+ emit selectionListActiveItemChanged(DeclarativeSelectionListModel::WordCandidateList, d->highlightIndex);
+ }
+ break;
+
+ default:
+ if (text.length() == 1) {
+ QChar c = text.at(0);
+ if (!d->input.contains(0x91CD) && CangjieTable::isLetter(c)) {
+ if (d->input.length() < (d->cangjieDictionary.simplified() ? CangjieTable::MAX_SIMPLIFIED_CODE_LENGTH : CangjieTable::MAX_CODE_LENGTH)) {
+ d->input.append(c);
+ ic->setPreeditText(d->input);
+ if (d->setCandidates(d->cangjieDictionary.getWords(d->input), true)) {
+ emit selectionListChanged(DeclarativeSelectionListModel::WordCandidateList);
+ emit selectionListActiveItemChanged(DeclarativeSelectionListModel::WordCandidateList, d->highlightIndex);
+ }
+ }
+ accept = true;
+ } else if (c.unicode() == 0x91CD) {
+ if (d->input.isEmpty()) {
+ d->input.append(c);
+ ic->setPreeditText(d->input);
+ d->checkSpecialCharInput();
+ }
+ accept = true;
+ } else if (c.unicode() == 0x96E3) {
+ if (d->input.length() == 1) {
+ Q_ASSERT(d->input.at(0).unicode() == 0x91CD);
+ d->input.append(c);
+ ic->setPreeditText(d->input);
+ d->checkSpecialCharInput();
+ }
+ accept = true;
+ }
+ }
+ if (!accept)
+ update();
+ break;
+ }
+ return accept;
+}
+
+QList<DeclarativeSelectionListModel::Type> TCInputMethod::selectionLists()
+{
+ return QList<DeclarativeSelectionListModel::Type>() << DeclarativeSelectionListModel::WordCandidateList;
+}
+
+int TCInputMethod::selectionListItemCount(DeclarativeSelectionListModel::Type type)
+{
+ Q_UNUSED(type)
+ Q_D(TCInputMethod);
+ return d->candidates.count();
+}
+
+QVariant TCInputMethod::selectionListData(DeclarativeSelectionListModel::Type type, int index, int role)
+{
+ QVariant result;
+ Q_D(TCInputMethod);
+ switch (role) {
+ case DeclarativeSelectionListModel::DisplayRole:
+ result = QVariant(d->candidates.at(index));
+ break;
+ case DeclarativeSelectionListModel::WordCompletionLengthRole:
+ result.setValue(0);
+ break;
+ default:
+ result = AbstractInputMethod::selectionListData(type, index, role);
+ break;
+ }
+ return result;
+}
+
+void TCInputMethod::selectionListItemSelected(DeclarativeSelectionListModel::Type type, int index)
+{
+ Q_UNUSED(type)
+ Q_D(TCInputMethod);
+ QString finalWord = d->candidates.at(index);
+ reset();
+ inputContext()->commit(finalWord);
+ if (d->setCandidates(d->phraseDictionary.getWords(finalWord.left(1)), false)) {
+ emit selectionListChanged(DeclarativeSelectionListModel::WordCandidateList);
+ emit selectionListActiveItemChanged(DeclarativeSelectionListModel::WordCandidateList, d->highlightIndex);
+ }
+}
+
+void TCInputMethod::reset()
+{
+ Q_D(TCInputMethod);
+ d->reset();
+}
+
+void TCInputMethod::update()
+{
+ Q_D(TCInputMethod);
+ if (d->highlightIndex >= 0) {
+ QString finalWord = d->pickHighlighted();
+ d->reset();
+ inputContext()->commit(finalWord);
+ } else {
+ inputContext()->clear();
+ d->reset();
+ }
+}
diff --git a/src/virtualkeyboard/tcinputmethod.h b/src/virtualkeyboard/tcinputmethod.h
new file mode 100644
index 00000000..480b535a
--- /dev/null
+++ b/src/virtualkeyboard/tcinputmethod.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd
+** All rights reserved.
+** For any questions to The Qt Company, please use contact form at http://qt.io
+**
+** This file is part of the Qt Virtual Keyboard module.
+**
+** Licensees holding valid commercial license for Qt may use this file in
+** accordance with the Qt License Agreement provided with the Software
+** or, alternatively, in accordance with the terms contained in a written
+** agreement between you and The Qt Company.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.io
+**
+******************************************************************************/
+
+#ifndef TCINPUTMETHOD_H
+#define TCINPUTMETHOD_H
+
+#include "abstractinputmethod.h"
+
+class TCInputMethodPrivate;
+
+class TCInputMethod : public AbstractInputMethod
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(TCInputMethod)
+ Q_PROPERTY(bool simplified READ simplified WRITE setSimplified NOTIFY simplifiedChanged)
+
+public:
+ explicit TCInputMethod(QObject *parent = 0);
+ ~TCInputMethod();
+
+ bool simplified() const;
+ void setSimplified(bool simplified);
+
+ QList<DeclarativeInputEngine::InputMode> inputModes(const QString &locale);
+ bool setInputMode(const QString &locale, DeclarativeInputEngine::InputMode inputMode);
+ bool setTextCase(DeclarativeInputEngine::TextCase textCase);
+
+ bool keyEvent(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers);
+
+ QList<DeclarativeSelectionListModel::Type> selectionLists();
+ int selectionListItemCount(DeclarativeSelectionListModel::Type type);
+ QVariant selectionListData(DeclarativeSelectionListModel::Type type, int index, int role);
+ void selectionListItemSelected(DeclarativeSelectionListModel::Type type, int index);
+
+ void reset();
+ void update();
+
+signals:
+ void simplifiedChanged();
+};
+
+#endif
diff --git a/src/virtualkeyboard/virtualkeyboard.pro b/src/virtualkeyboard/virtualkeyboard.pro
index 5c03350b..17c67e45 100644
--- a/src/virtualkeyboard/virtualkeyboard.pro
+++ b/src/virtualkeyboard/virtualkeyboard.pro
@@ -58,9 +58,10 @@ RESOURCES += \
content/content.qrc
pinyin: RESOURCES += content/layouts_pinyin.qrc
+tcime: RESOURCES += content/layouts_traditional_chinese.qrc
hangul: RESOURCES += content/layouts_hangul.qrc
openwnn: RESOURCES += content/layouts_japanese.qrc
-!pinyin:!hangul:!openwnn: RESOURCES += content/layouts.qrc
+!tcime:!pinyin:!hangul:!openwnn: RESOURCES += content/layouts.qrc
retro-style {
DEFINES += QT_VIRTUALKEYBOARD_DEFAULT_STYLE=\\\"retro\\\"
@@ -148,6 +149,22 @@ pinyin {
INSTALLS += pinyin_data
}
+tcime {
+ SOURCES += \
+ tcinputmethod.cpp
+ HEADERS += \
+ tcinputmethod.h
+ DEFINES += HAVE_TCIME
+ INCLUDEPATH += 3rdparty/tcime
+ DEPENDPATH += 3rdparty/tcime
+ LIBS += -L$$OUT_PWD/3rdparty/tcime/$$SUBPATH -ltcime
+ tcime_data.files = \
+ $$PWD/3rdparty/tcime/data/qt/dict_cangjie.dat \
+ $$PWD/3rdparty/tcime/data/qt/dict_phrases.dat
+ tcime_data.path = $$DATAPATH/tcime
+ INSTALLS += tcime_data
+}
+
hangul {
SOURCES += \
hangulinputmethod.cpp \
diff --git a/tests/auto/inputpanel/data/inputpanel/inputpanel.qml b/tests/auto/inputpanel/data/inputpanel/inputpanel.qml
index 6cf395b7..113431c2 100644
--- a/tests/auto/inputpanel/data/inputpanel/inputpanel.qml
+++ b/tests/auto/inputpanel/data/inputpanel/inputpanel.qml
@@ -46,6 +46,7 @@ InputPanel {
readonly property var availableLocales: VirtualKeyboardSettings.availableLocales
readonly property var activeLocales: VirtualKeyboardSettings.activeLocales
readonly property int inputMode: InputContext.inputEngine.inputMode
+ readonly property var inputMethod: InputContext.inputEngine.inputMethod
readonly property var keyboard: Utils.findChildByProperty(inputPanel, "objectName", "keyboard", null)
readonly property bool handwritingMode: keyboard.handwritingMode
readonly property var keyboardLayoutLoader: Utils.findChildByProperty(keyboard, "objectName", "keyboardLayoutLoader", null)
@@ -175,7 +176,9 @@ InputPanel {
function setLocale(inputLocale) {
VirtualKeyboardSettings.locale = inputLocale
- return Qt.inputMethod.locale.name.substring(0, 2) === inputLocale.substring(0, 2)
+ if (["ar", "fa"].indexOf(inputLocale.substring(0, 2)) !== -1)
+ return Qt.inputMethod.locale.name.substring(0, 2) === inputLocale.substring(0, 2)
+ return Qt.inputMethod.locale.name === inputLocale
}
function setActiveLocales(activeLocales) {
@@ -191,6 +194,8 @@ InputPanel {
return InputEngine.Dialable
else if (inputModeName === "Pinyin")
return InputEngine.Pinyin
+ else if (inputModeName === "Canjie")
+ return InputEngine.Canjie
else if (inputModeName === "Hangul")
return InputEngine.Hangul
else if (inputModeName === "Hiragana")
diff --git a/tests/auto/inputpanel/data/tst_inputpanel.qml b/tests/auto/inputpanel/data/tst_inputpanel.qml
index a589acd9..d0cb4356 100644
--- a/tests/auto/inputpanel/data/tst_inputpanel.qml
+++ b/tests/auto/inputpanel/data/tst_inputpanel.qml
@@ -701,6 +701,59 @@ Rectangle {
compare(textInput.text, data.outputText)
}
+ function test_cangjieInputMethod_data() {
+ return [
+ // "vehicle"
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u5341\u7530\u5341", expectedCandidates: [ "\u8ECA" ], outputText: "\u8ECA" },
+ // simplified mode: "vehicle"
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: true, inputSequence: "\u5341\u5341", expectedCandidates: [ "\u8ECA" ], outputText: "\u8ECA" },
+ // "to thank"
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u535C\u53E3\u7AF9\u7AF9\u6208", expectedCandidates: [ "\u8B1D" ], outputText: "\u8B1D" },
+ // exceptions: "door"
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u65E5\u5F13", expectedCandidates: [ "\u9580" ], outputText: "\u9580" },
+ // exceptions: "small table"
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u7AF9\u5F13", expectedCandidates: [ "\u51E0" ], outputText: "\u51E0" },
+ // fixed decomposition
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u7AF9\u96E3", expectedCandidates: [ "\u81FC" ], outputText: "\u81FC" },
+ // input handling: valid input sequence + space
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u5341\u7530\u5341 ", outputText: "\u8ECA" },
+ // input handling: invalid input sequence + space
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u5341\u7530 ", outputText: "" },
+ // input handling: valid input sequence + enter
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u5341\u7530\u5341\n", outputText: "\u8ECA\n" },
+ // input handling: invalid input sequence + enter
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u5341\u7530\n", outputText: "\n" },
+ // input handling: valid input sequence + punctuation
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u5341\u7530\u5341\uFF0E", outputText: "\u8ECA\uFF0E" },
+ // input handling: invalid input sequence + punctuation
+ { initInputMethodHints: Qt.ImhNone, initLocale: "zh_TW", initSimplified: false, inputSequence: "\u5341\u7530\uFF0E", outputText: "\uFF0E" },
+ ]
+ }
+
+ function test_cangjieInputMethod(data) {
+ prepareTest(data)
+
+ if (data.hasOwnProperty("initSimplified")) {
+ if (inputPanel.inputMethod.simplified !== data.initSimplified)
+ verify(inputPanel.virtualKeyClick(Qt.Key_Mode_switch))
+ verify(inputPanel.inputMethod.simplified === data.initSimplified)
+ }
+
+ for (var inputIndex in data.inputSequence) {
+ verify(inputPanel.virtualKeyClick(data.inputSequence[inputIndex]))
+ }
+ waitForRendering(inputPanel)
+
+ if (data.expectedCandidates) {
+ for (var candidateIndex in data.expectedCandidates) {
+ verify(inputPanel.selectionListSearchSuggestion(data.expectedCandidates[candidateIndex]))
+ verify(inputPanel.selectionListSelectCurrentItem())
+ }
+ }
+
+ compare(textInput.text, data.outputText)
+ }
+
function test_hangulInputMethod_data() {
return [
// Test boundaries of the Hangul Jamo BMP plane