среда, 5 сентября 2012 г.

Формирование QString (Qt) из std::string содержащих национальные символы

Как сделать QString (Qt) из std::string с русскими буквами

Занимался я сегодня написанием некоторого демонстрационно-тестового приложения с использованием Qt. Приложение это должно выполнять роль GUI-обертки над объектами некой специализированной библиотеки, которую я написал в boost для некоторой прикладной области.

Работа выполняется в Linux. Дистрибутив Ubuntu 11.10. Локаль - UTF-8.

И вот возникла у меня проблема. Средствами boost::system::error_code, в ядре моей библиотеки формировалось некоторое локализованное сообщение (т.е. на русском языке), которое мне понадобилось отобразить средствами Qt в экземпляре класса QTextEdit.

Вообще, надо бы давно запретить использование национальных языков в системных сообщениях. Однако, видимо, это кому-то кажется недемократичным, поэтому программисты ежедневно тысячами подрываются на этих проблемах и мы постоянно в готовых приложениях сталкиваемся с кракозябрами там, где могли бы прочитать нормальный английский текст. Ведь в чем проблема? Домохозяйки не удосуживаются читать даже сообщения прикладного уровня, и представить домохозяйку, которая поймет, что надо делать прочитав системное сообщение из сетевой подсистемы ядра типа "Адрес уже используется" на родном языке, мне кажется невероятным. А раз это не для домохозяйки, то зачем усложнять жизнь специалистам, которые все поголовно умеют читать по английски? К этому еще можно добавить проблему некорректных переводов. Понятно, вопрос риторический. Однако, хочется высказаться.

На самом деле проблемы я не понял и был крайне удивлен, когда преобразовав полученное сообщение из std::string в QString и выведя его потом в окно редактора я увидел кракозябры. Действительно. В чем может быть проблема? Если бы я, не дай бог, работал под Windows, то удивляться бы было не чему. Давно не интересовался как там дела сейчас, но во времена Windows XP меня веселило три одновременно используемые кодовые страницы в русских версиях операционной системы. Вот уж действительно, не операционная система а система заплаток. Но откуда могла взяться проблема в Linux? Если в ней, в используемой мной сборке, используется одна кодовая страница UTF-8 во всех подсистемах ядра и пользовательского пространства.

Проблема решется просто. Приведу ниже максимально подробный вариант решения с комментариями.

  QTextCodec *codec = QTextCodec::codecForName("UTF8");
  if (codec)
  {
    std::string str = boost_lib->getLastError(); // Get string from a boost library
    QByteArray ba(str.c_str());                  // Convert to QByteArray
    QString msg = codec->toUnicode(ba);          // Qt magic !!! 

    m_pteLog->append(msg);                       // Append msg to a QTextEdit object
  }

В общем, заплатку я нашел, но в проблеме разбираться не стал. Видимо, по умолчанию, текст получаемый в Qt из строковых однобайтовых типов воспринимаются в кодировке Latin1, поэтому и возникала, в моем случае, неприятная неправильная перекодировка.

В заключении этой короткой заметки я бы хотел выразить надежду, что если кто-нибудь из читателей знает подробности затрагиваемого здесь механизма трансляции кодов символов, то пусть он его объяснит в комментариях или письмом мне, а я сделаю дополнение.