Qt convert unicode entities - c++

In QT 5.4 and C++ I try to decode a string that has unicode entities.
I have this QString:
QString string = "file\u00d6\u00c7\u015e\u0130\u011e\u00dc\u0130\u00e7\u00f6\u015fi\u011f\u00fc\u0131.txt";
I want to convert this string to this: fileÖÇŞİĞÜİçöşiğüı.txt
I tried QString's toUtf8 and fromUtf8 methods. Also tried to decode it character by character.
Is there a way to convert it by using Qt?

Qt provides a macro called QStringLiteral for handling string literals correctly.
Here's a full working example:
#include <QString>
#include <QDebug>
int main(void) {
QString string = QStringLiteral("file\u00d6\u00c7\u015e\u0130\u011e\u00dc\u0130\u00e7\u00f6\u015fi\u011f\u00fc\u0131.txt");
qDebug() << string;
return 0;
}
As mentioned in the above comments, you do need to print to a console that supports these characters for this to work.

I have just tested this code:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString s = "file\u00d6\u00c7\u015e\u0130\u011e\u00dc\u0130\u00e7\u00f6\u015fi\u011f\u00fc\u0131.txt";
qDebug() << s.length(); //Outputs: 22
qDebug() << s; //Outputs: fileÖÇŞİĞÜİçöşiğüı.txt
return a.exec();
}
This is with Qt 5.4 on ubuntu, so it looks like your problem is with some OS only.

#include <QTextDocument>
QTextDocument doc;
QString string = "file\u00d6\u00c7\u015e\u0130\u011e\u00dc\u0130\u00e7\u00f6\u015fi\u011f\u00fc\u0131.txt";
doc.setHtml(string); // to convert entities to text
QString result = doc.toPlainText(); // result = "fileÖÇŞİĞÜİçöşiğüı.txt"
NOT USEFUL if you have a CONSOLE app
QTextDocument needs the GUI module.

Related

Why QXmlQuery seem to add a ` \n` to results? (and how to solve it?)

Writing a little code to extract some values from an XML, the result of the XPath seem to add \n after the content.
#include <QCoreApplication>
#include <QXmlQuery>
#include <QString>
#include <QDebug>
auto main(int argn, char* argc[])->int
{
QCoreApplication app(argn, argc);
QString replyContent="<Root isOk='ok'/>";
QXmlQuery query;
query.setFocus(replyContent);
query.setQuery("string(//#isOk)");
// Attribute seem to add \n
QString queryResult;
if (query.evaluateTo(&queryResult))
{
qDebug() << queryResult; // Where this \n come from?
qDebug() << queryResult.size(); // Why 3? shouldn't be 2?
}
}
Expected result:
"ok"
2
Given result:
"ok\n"
3
This obviously has some side effects which I would like to avoid.
Why is this \n added? And how to solve it?
I think that this is introduced by the QXmlFormatter that is used when serialising the results to a QString; I suspect that QXmlFormatter::endDocument writes a newline.
One workaround would be to output to a string list instead, then pick the first element:
QStringList results;
if (query.evaluateTo(&results))
{
const QString& queryResult = results.first();
qDebug() << queryResult;
qDebug() << queryResult.size();
}
You might choose to join() the results instead, if you need them all.
Alternatively you can take full control of the serialization and use either QXmlSerializer or QXmlFormatter. That way you will have in the output whatever you ask, not some defaults you are provided with. It will have more code, that's true but the intent will be clearer than just discarding some newline at the end.
Here is an example of how to do it with QXmlSerializer (which produces no redundant symbols by default):
#include <QCoreApplication>
#include <QXmlQuery>
#include <QXmlSerializer>
#include <QString>
#include <QBuffer>
#include <QDebug>
auto main(int argn, char* argc[])->int
{
QCoreApplication app(argn, argc);
QString replyContent="<Root isOk='ok'/>";
QXmlQuery query;
query.setFocus(replyContent);
query.setQuery("string(//#isOk)");
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QXmlSerializer serializer(query, &buffer);
if (query.evaluateTo(&serializer))
{
QString queryResult = QString::fromUtf8(buffer.buffer());
qDebug() << queryResult;
qDebug() << queryResult.size();
}
}

QT Reading binary file and then convert it to QString

I saved the QString in the file like this:
QString str="blabla";
QByteArray _forWrite=QByteArray::fromHex(str.toLatin1());
f.write(_forWrite); // f is the file that is opened for writing.
Then when I read the file I use QFile::readAll() to take the QByteArray but I don't know how to convert it to QString.
I tried to use the constructor that uses QByteArray but It didn't work out. I tried also with QByteArray::data() but same result. What I do wrong ?
It's not clear why you are calling QByteArray::fromHex at all. toLatin1() already return you QByteArray where each symbol encoded with one byte.
[UPDATE]
You should NOT call QByteArray::fromHex at all, because:
invalid characters in the input are skipped
And invalid characters are characters that are not the numbers 0-9 and the letters a-f
You can use QDataStream
#include <QApplication>
#include <QDataStream>
#include <QByteArray>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QString strToWrite = "blabla";
QFile fileToWrite("file.bin");
QDataStream dataStreamWriter(&fileToWrite);
fileToWrite.open(QIODevice::WriteOnly);
dataStreamWriter << strToWrite;
fileToWrite.close();
QString strToRead = "";
QFile fileToRead("file.bin");
QDataStream dataStreamReader(&fileToRead);
fileToRead.open(QIODevice::ReadOnly);
dataStreamReader >> strToRead;
fileToRead.close();
qDebug() << strToRead;
return app.exec();
}
Output : "blabla"

How to print unicode characters using Qt?

I'm trying to do something very simple, I just want to print my native language, pt-br in Windows Console.
IDE Creator
I created a new project->other->Qt Console Application the I put it in my main.cpp file:
#include <QCoreApplication>
#include <QDebug>
#include <QTextCodec>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "aeiou áéíóú";
std::cout << "aeiou áéíóú" << endl;
return 0;
}
here is what I got:
C:\Users\maiko.costa\testeQtConsole\debug>testeQtConsole.exe
aeiou ßÚݾ·
aeiou ßÚݾ·
C:\Users\maiko.costa\testeQtConsole\debug>
I've tried it too, but with the same previous output:
#include <QCoreApplication>
#include <QDebug>
#include <QTextCodec>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextCodec *codec = QTextCodec::codecForName("CP1252");
QTextCodec::setCodecForCStrings(codec);
qDebug() << "aeiou áéíóú";
std::cout << "aeiou áéíóú" << endl;
return 0;
}
The System encode for Windows 7 is it right ?
what am I missing ?
I am not that familiar with QT but I think this can help you just as well. The Windows console uses the OEM char set. Therefore, in order to properly print characters on std::cout they need to be encoded using OEM. This can be accomplished using the Windows API CharToOem.
Small example, just so you get the idea (here input is assumed to be UTF16):
void oemPrint(const wchar_t* str) {
char* chars = (char*)alloca(strlen(str)+1);
CharToOemW(str, chars);
fputs(chars, stdout);
}
// Usage:
oemPrint(L"aeiou áéíóú");
EDIT: A QT solution might be to use QTextCodec::codecForName("IBM 850") - this is the OEM codec.
I find the solution in this thread. Output unicode strings in Windows console app
If I ran chcp 65001 in windows console before I ran my app the characters are printed correctly.
I don't know how to workaround it in my source code, then I call this program manually with the start cpp function.
Here is the return line of function I wrote that displays passwords as ● ● ● ● ●
return QString::fromUtf8( "\u25CF \u25CF \u25CF \u25CF \u25CF" );
QString::fromUnicode should work the same.
Maybe something like:
QString x = QString::fromUtf8( "\u25CF \u25CF \u25CF \u25CF \u25CF" );
std::cout << qPrintable(x) << std::endl;
Of course change it to QString::fromUnicode... hope this helps
QString a="aeiou áéíóú";
std::cout<< a.toStdString().data();

How to handle Korean character set between QT & Oracle

I'd like to use Oracle with ODBC.
I could get data from Oracle successfully. But Korean character is broken like ????.
As all programmer said on internet forum, I tried to apply QTextCodec like below.
I tried EUC-KR and other codec names. But no change.
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QSqlQuery q("select * from temp", db);
q.setForwardOnly(true);
QString contect= "";
while(q.next())
{
QByteArray name = q.value(0).toByteArray();
QString age = q.value(1).toString();
contect = contect + codec->toUnicode(name);
ui.textEdit->setText(contect);
}
Oracle side info is.....
NLS_CHARACTERSET : KO16MSWIN949
NLS_NCHAR_CHARACTERSET : AL16UTF16
NLS_LANG : KOREAN_KOREA.KO16MSWIN949
I'm developing with eclipse (on windows 7) and the default file text encoding is utf-8.
I'll appreciate it if you give me comment.
Thanks.
I think you need to change the codec name as you need a codec from the Korean character set into UTF8.
Try changing your code to:
QTextCodec *codec = QTextCodec::codecForName("cp949");
As the Wikipedia page for Code page 949 mentions that it is non-standard Microsoft version of EUC-KR, you could also try EUC-KR.
Try the following program to get the list of text codecs and aliases:
test.cpp
#include <QtCore>
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
const auto codecs = QTextCodec::availableCodecs();
for (auto it = codecs.begin(); it != codecs.end(); ++it)
{
const auto codec = QTextCodec::codecForName(*it);
qDebug() << codec->name() << codec->aliases();
}
return 0;
}
test.pro
QT += core
SOURCES=test.cpp
QMAKE_CXXFLAGS += -std=c++0x
Note that the program uses auto for brevity, but this requires a C++11 compiler (tested on GCC 4.4).

Connecting to the new Bluez HDP plugin using DBUS from QT/C++

I'm attempting to get readings from a device using the bluetooth Health Device Profile (specifically, an Nonin Onyx II 9560BT). Using this guide, I've been able to do so using python over dbus. Now I'm trying to port it over to C++, and as I'm already using QT in the application, I'm using the QT DBus bindings.
So far I've gotten to the following short program based on this API to test it:
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtDBus/QtDBus>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
if (!QDBusConnection::sessionBus().isConnected()) {
fprintf(stderr, "Cannot connect to the D-Bus session bus.\n"
"To start it, run:\n"
"\teval `dbus-launch --auto-syntax`\n");
return 1;
}
QDBusInterface iface("org.bluez","/org/bluez","org.bluez.HealthManager",QDBusConnection::systemBus(),0);
QVariantMap map;
map.insert("DataType",ushort(1004));//same result with simply 1004
map.insert("Role","Sink");
map.insert("Description","HDP Test Manager"); //Optional
//map.insert("ChannelType","Reliable");//Optional, same result with or without
//QList<QVariant> argumentList;
//argumentList.append(map);
QDBusPendingReply<> r = iface.call("CreateApplication",map);
qDebug() << r.reply();
qDebug() << r.error();
return 0;
}
As far as I can tell, the dict object taken by "CreateApplication" corresponds to an a{sv} which in QT corresponds to the QVariantMap.
However, I keep getting this error:
QDBusMessage(type=Error, service="", error name="org.bluez.Error.InvalidArguments", error message="Invalid arguments in method call", signature="", contents=([]) )
Question: What am I doing wrong?
Based on the guides at freedesktop.org, the qt docs and the mighty google, this is as far as I've gotten.
Thanks for any/all help!
/Keyz182
It works now. It seems that the ushort(0x1004) was getting cast by the QVariant to an int, and thus being picked up as a uint32 by the bluez code, which is not what was expected.
To fix it I did the following (there may be another way, but this worked for me).
I added a Metatype declaration for ushort, then registered it. then, created a QVariant containing the value, and used the QVariants convert method to set the metatype as a ushort (or uint16 when exposed to dbus).
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtDBus/QtDBus>
Q_DECLARE_METATYPE(ushort); //Added this to declare ushort as a metatype
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
int ushorttype = qDBusRegisterMetaType<ushort>(); //Register the ushort metatype and get it's id
if (!QDBusConnection::sessionBus().isConnected()) {
fprintf(stderr, "Cannot connect to the D-Bus session bus.\n"
"To start it, run:\n"
"\teval `dbus-launch --auto-syntax`\n");
return 1;
}
QDBusInterface iface("org.bluez","/org/bluez","org.bluez.HealthManager",QDBusConnection::systemBus(),0);
QVariant dt(0x1004);
dt.convert((QVariant::Type)ushorttype); //convert to the new type
QVariantMap map;
map.insert("DataType",dt);
map.insert("Role","Sink");
map.insert("Description","HDP Test Manager"); //Optional
QDBusPendingReply<> r = iface.call("CreateApplication",map);
qDebug() << r.isValid();
qDebug() << r.reply();
return 0;
}