Автор : Сукиязов Сергей Александрович (2007 г., статья не закончена)
В 2006 году вышла в свет 4-я версия одной из популярных библиотек для организации графического пользовательского интерфейса (GUI) - Qt Toolkit, разработанной норвежской фирмой Troll Tech.
В предыдущей статье "Использование Qt-2.2.x в русскоязычных программах", рассматривались вопросы связанные с использованием класса QString для работы со строками. Библиотека Qt четвертой версии также использует для работы с текстовыми строками класс QString. Хотя спецификация этого класса претерпела значительные изменения, все аспекты рассматриваемые в статье "Использование Qt-2.2.x в русскоязычных программах" полностью применимы и к этой версии библиотеки. Начиная с версии 3.x добавилась возможность задавать кодек по умолчанию, который используется в конструкторе класса QString(const char *). Это такие методы, как:
void QTextCodec::setCodecForCStrings ( QTextCodec * codec )
Устанавливает кодек, который будет использоваться классом QString для преобразования из типа/в тип const char * и QByteArray. Если значение codec
равно 0 (по умолчанию), то класс QString принимает при преобразовании Latin-1 значения.
В большинстве случаев использование этого метода в функции main(...)
для установки кодека по умолчанию в значение возвращаемое методомQTextCodec::codecForLocale()
позволяет избежать большинства ошибок связанных с некорректным преобразованием из/в UNICODE. Обязательно перед вызовом метода QTextCodec::codecForLocale()
необходимо убедиться что установлена требуемая локаль. Пример программы, использующей этот метод:
#include <QtCore> const char *gUsedCodeset = "CP 1251"; int main(int aArgc, cgar *apArgv) { QTextCodec *vpCodec = QTextCodec::codecForName(gUsedCodeset); if(vpCodec) { QTextCodec::setCodecForCStrings(vpCodec); } QString vString = "Привет мир!!!"; qWarning() << vString; return 0; }
В этом примере кодек устанавливается для заранее заданной кодировки. В других ситуациях имя кодировки можно получать из установок локали:
#include <QtCore> #include <locale.h> int main(int aArgc, cgar *apArgv) { setlocale(LC_ALL,""); QTextCodec *vpCodec = QTextCodec::codecForLocale(); if(vpCodec) { QTextCodec::setCodecForCStrings(vpCodec); } QString vString = "Привет мир!!!"; qWarning() << vString; return 0; }
В приведенном выше примере, устанавливается кодек соответствующий кодировки текущей локали. С одной стороны проблемы с преобразованием строк решены. Но остается проблема касающаяся C-like строк заданных в виде констант, например:
... QString vString = "Привет мир!!!"; ...
Строковая константа "Привет мир!!!"
будет задана в кодировке соответствующей локали в которой набирался исходный код. В общем случае, скомпилированное приложение, может быть запущено в локали, кодировка которой отличается от кодировки в которой создавались исходные коды программы. В этом случае, несмотря на установку кодека по умолчанию, результат преобразования будет некорректным.
В программе, использующей библиотеку Qt, может возникнуть две ситуации, в которых требуется преобразование из типов в тип QString:
Таким образом, если в программе выполняется инициализация строк типа QString строковыми константами типа const char *
или QByteArray
, необходимо реализовать специальный механизм который должен будет учитывать кодировку в которой создавались исходные коды для корректного преобразования.
К сожалению, языки C и C++ не имеют специальных возможностей для того, чтобы можно было задать кодировку символов, используемую при создании исходных текстов.
Для того чтобы задать кодировку символов, можно воспользоваться препроцессором языка C. С помощью специального макроопределения можно задать имя используемой кодировки. Это макроопределение необходимо поместить в начало файла с исходными кодами программы, до подключения заголовочных файлов. Также это макроопределение можно задать с помощью параметров компилятора. Например:
//! -*- coding: UTF-8 -*-
#define SOURCE_CODING "UTF-8"
extern "C" {
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <syslog.h>
}
#include <QtCore>
#include "defines.h"
...
В приведённом выше примере, имя кодировки,используемой для создания исходных кодов программы, задается с помощью макроопределения SOURCE_CODING
. Далее, с помощью препроцессора (условной компиляции) можно создать специальные функции для преобразования из типа const char *
и QByteArray
в тип QString
. Эти функции выполняются как inline и размещаются в заголовочном файле defines.h
, который включается в каждый файл, содержащий исходные коды программы.
Эта функция может быть определена следующим образом:
//! function
inline QString _(const char *apStr) {
QTextCodec *vpCodec = 0;
#ifdef SOURCE_CODING
vpCodec = QTextCodec::codecForName(SOURCE_CODING);
#else
vpCodec = QTextCodec::codecForLocale();
#endif
if(!vpCodec) vpCodec = QTextCodec::codecForMib(4); // 4 -> ISO-8859-1, 106 – UTF-8
if(vpCodec) return vpCodec->toUnicode(apStr);
return QString(apStr);
}
Приведенная выше функция, использует для преобразования кодек соответствующей кодировке определенной с помощью макроопределения SOURCE_CODING
, если макроопределение с таким именем не существует, то используется кодек соответствующий локали в которой выполняется программа. Т.о. исходный код программы будет иметь следующий вид (функцию _(...)
помещаем в заголовочный файл defines.h
):
//! -*- coding: UTF-8 -*-
#define SOURCE_CODING "UTF-8"
#include <QtCore>
#include <locale.h>
#include "defines.h"
int main(int aArgc, cgar *apArgv) {
setlocale(LC_ALL,"");
QTextCodec *vpCodec = QTextCodec::codecForLocale();
if(vpCodec) {
QTextCodec::setCodecForCStrings(vpCodec);
}
QString vString = _("Привет мир!!!");
qWarning() << vString;
return 0;
}
В приведенном выше примере, переменная vString всегда будет получать корректное UNICODE значение, независимо от локали в которой оно запущено.