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();
}