QtQuick で全角文字を半角に変換する
はじめに
昨日書いた Qt 5 で全角文字を半角に変換する #01 に以下のようなフィードバックがありました。
ここでいう「プラグイン」というのは QNeptunea という Nokia N9 上で動く Twitter Client の機能を拡張するプラグインで、「苦労」とは これ とか これ の変更のことを指しています。
パッチ を見てもらえるわかるかと思いますが、実際にこの機能の実装は 20行程度 で、Qt のバージョンに依存するようなコードではないので、Qt 4 でも簡単に同じ事が実現できます。
作ったもの
ということで、QtQuick 1.x から Transliterate するような 簡単なサンプルを作ってみました 。取得の仕方などは http://qtquick.me/ の「Readonly access」を参照してください。
import QtQuick 1.1 import me.qtquick.transliterator 0.1 Text { id: halfwidth Transliterator { id: transliterator type: 'Fullwidth-Halfwidth' } Component.onCompleted: halfwidth.text = transliterator.transliterate('123ABC') }
のように使うことができます。便利ですね。
C++ 側
こんな感じに実装されています。
#include <QtDeclarative> #include <unicode/utypes.h> #include <unicode/unistr.h> #include <unicode/translit.h> class QTransliterator : public QObject { Q_OBJECT Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged) Q_PROPERTY(QStringList availableTypes READ availableTypes NOTIFY availableTypesChanged) public: QTransliterator(QObject *parent = 0); const QString &type() const; const QStringList &availableTypes() const; Q_INVOKABLE QString transliterate(const QString &text); public slots: void setType(const QString &type); signals: void typeChanged(const QString &type); void availableTypesChanged(const QStringList &availableTypes); private slots: void createTransliterator(const QString &type); private: QString icu2qt(const icu::UnicodeString &string); icu::UnicodeString qt2icu(const QString &string); private: QString m_type; QStringList m_availableTypes; icu::Transliterator *m_transliterator; }; QTransliterator::QTransliterator(QObject *parent) : QObject(parent) , m_transliterator(0) { int count = icu::Transliterator::countAvailableIDs(); for (int i = 0; i < count; i++) { icu::UnicodeString id = icu::Transliterator::getAvailableID(i); m_availableTypes.append(icu2qt(id)); } connect(this, SIGNAL(typeChanged(QString)), this, SLOT(createTransliterator(QString))); } const QString &QTransliterator::type() const { return m_type; } void QTransliterator::setType(const QString &type) { if (m_type == type) return; if (m_availableTypes.contains(type)) { m_type = type; emit typeChanged(type); } else { qWarning() << type << tr("is not supported"); qWarning() << m_availableTypes; } } const QStringList &QTransliterator::availableTypes() const { return m_availableTypes; } void QTransliterator::createTransliterator(const QString &type) { if (m_transliterator) { delete m_transliterator; m_transliterator = 0; } UErrorCode status = U_ZERO_ERROR; m_transliterator = icu::Transliterator::createInstance(qt2icu(type), UTRANS_FORWARD, status); } QString QTransliterator::transliterate(const QString &text) { QString ret; if (m_transliterator) { UnicodeString str = qt2icu(text); m_transliterator->transliterate(str); ret = icu2qt(str); } return ret; } QString QTransliterator::icu2qt(const icu::UnicodeString &string) { int len = string.length(); QString ret(len, Qt::Uninitialized); string.extract(0, len, reinterpret_cast<UChar *>(ret.data())); return ret; } icu::UnicodeString QTransliterator::qt2icu(const QString &string) { return icu::UnicodeString::fromUTF8(string.toUtf8().constData()); } #include "main.moc" int main(int argc, char *argv[]) { QApplication app(argc, argv); qmlRegisterType<QTransliterator>("me.qtquick.transliterator", 0, 1, "Transliterator"); QDeclarativeView view(QUrl("qrc:/transliterator.qml")); view.show(); return app.exec(); }