QT convert string to UTF-8 - qt

I'm having some troubles converting a string Bob Rosén to Bob Rosén
Tried:
QString str = v.toObject().value("name").toString(); // Contains Bob Rosén
qDebug() << str.toUtf8(); // Outputs Bob Rosén
Any ideas?

Following works for me. A more elegant solution may exist.
QString str = "Bob Rosén";
qDebug() << QString::fromUtf8(str.toLatin1().constData());

Related

QString remove last characters

How to remove /Job from /home/admin/job0/Job
QString name = "/home/admin/job0/Job"
I want to remove last string after"/"
You have QString::chop() for the case when you already know how many characters to remove.
It is same as QString::remove(), just works from the back of string.
Find last slash with QString::lastIndexOf.
After that get substring with QString::left till the position of the last slash occurrence
QString name = "/home/admin/job0/Job";
int pos = name.lastIndexOf(QChar('/'));
qDebug() << name.left(pos);
This will print:
"/home/admin/job0"
You should check int pos for -1 to be sure the slash was found at all.
To include last slash in output add +1 to the founded position
qDebug() << name.left(pos+1);
Will output:
"/home/admin/job0/"
Maybe easiest to understand for later readers would probably be:
QString s("/home/admin/job0/Job");
s.truncate(s.lastIndexOf(QChar('/'));
qDebug() << s;
as the code literaly says what you intended.
You can do something like this:
QString s("/home/admin/job0/Job");
s.remove(QRegularExpression("\\/(?:.(?!\\/))+$"));
// s is "/home/admin/job0" now
If you are using Qt upper than 6 and sure that "/" constains in your word you should use QString::first(qsizetype n) const function instead QString::left(qsizetype n) const
Example:
QString url= "/home/admin/job0/Job"
QString result=url.first(lastIndexOf(QChar('/')));
If you run these code:
QElapsedTimer timer;
timer.start();
for (int j=0; j<10000000; j++)
{
QString name = "/home/admin/job0/Job";
int pos = name.lastIndexOf("/");
name.left(pos);
}
qDebug() << "left method" << timer.elapsed() << "milliseconds";
timer.start();
for (int j=0; j<10000000; j++)
{
QString name = "/home/admin/job0/Job";
int pos = name.lastIndexOf(QChar('/'));
name.first(pos);
}
qDebug() << "frist method" << timer.elapsed() << "milliseconds";
Results:
left method 10034 milliseconds
frist method 8098 milliseconds
sorry for replying to this post after 4 years, but I have (I think) the most efficient answer.
You can use
qstr.remove(0, 1); //removes the first character
qstr.remove(1, 1); //removes the last character
Thats everything you have to do, to delete characters ONE BY ONE (first or last) from a QString, until 1 character remains.

Pass a string from ECL to C++

I'm trying to get into the fascinating world of Common Lisp embedded in C++. My problem is that I can't manage to read and print from c++ a string returned by a lisp function defined in ECL.
In C++ I have this function to run arbitrary Lisp expressions:
cl_object lisp(const std::string & call) {
return cl_safe_eval(c_string_to_object(call.c_str()), Cnil, Cnil);
}
I can do it with a number in this way:
ECL:
(defun return-a-number () 5.2)
read and print in C++:
auto x = ecl_to_float(lisp("(return-a-number)"));
std::cout << "The number is " << x << std::endl;
Everything is set and works fine, but I don't know to do it with a string instead of a number. This is what I have tried:
ECL:
(defun return-a-string () "Hello")
C++:
cl_object y = lisp("(return-a-string)");
std::cout << "A string: " << y << std::endl;
And the result of printing the string is this:
A string: 0x3188b00
that I guess is the address of the string.
Here it is a capture of the debugger and the contents of the y cl_object. y->string.self type is an ecl_character.
Debug
(Starting from #coredump's answer that the string.self field provides the result.)
The string.self field is defined as type ecl_character* (ecl/object.h), which appears to be given in ecl/config.h as type int (although I suspect this is slightly platform dependent). Therefore, you will not be able to just print it as if it was a character array.
The way I found worked for me was to reinterpret it as a wchar_t (i.e. a unicode character). Unfortunately, I'm reasonably sure this isn't portable and depends both on how ecl is configured and the C++ compiler.
// basic check that this should work
static_assert(sizeof(ecl_character)==sizeof(wchar_t),"sizes must be the same");
std::wcout << "A string: " << reinterpret_cast<wchar_t*>(y->string.self) << std::endl;
// prints hello, as required
// note the use of wcout
The alternative is to use the lisp type base-string which does use char (base-char in lisp) as its character type. The lisp code then reads
(defun return-a-base-string ()
(coerce "Hello" 'base-string))
(there may be more elegant ways to do the conversion to base-string but I don't know them).
To print in C++
cl_object y2 = lisp("(return-a-base-string)");
std::cout << "Another: " << y2->base_string.self << std::endl;
(note that you can't mix wcout and cout in the same program)
According to section 2.6 Strings of The ECL Manual, I think that the actual character array is found by accessing the string.self field of the returned object. Can you try the following?
std::cout << y->string.self << std::endl;
std::string str {""};
cl_object y2 = lisp("(return-a-base-string)");
//get dimension
int j = y2->string.dim;
//get pointer
ecl_character* selv = y2->string.self;
//do simple pointer addition
for(int i=0;i<j;i++){
str += (*(selv+i));
}
//do whatever you want to str
this code works when the string is build from ecl_characters
from the documentation:
"ECL defines two C types to hold its characters: ecl_base_char and ecl_character.
When ECL is built without Unicode, they both coincide and typically match unsigned char, to cover the 256 codes that are needed.
When ECL is built with Unicode, the two types are no longer equivalent, with ecl_character being larger.
For your code to be portable and future proof, use both types to really express what you intend to do."
On my system the return-a-base-string is not needed, but I think it could be good to add for compatibility. I use the (ecl) embedded CLISP 16.1.2 version.
The following piece of code reads a string from lisp and converts to C++ strings types - std::string and c-string- and store them on C++ variables:
// strings initializations: string and c-string
std::string str2 {""};
char str_c[99] = " ";
// text read from clisp, whatever clisp function that returns string type
cl_object cl_text = lisp("(coerce (text-from-lisp X) 'base-string)");
//cl_object cl_text = lisp("(text-from-lisp X)"); // no base string conversions
// catch dimension
int cl_text_dim = cl_text->string.dim;
// complete c-string char by char
for(int ind=0;i<cl_text_dim;i++){
str_c[i] = ecl_char(cl_text,i); // ecl function to get char from cl_object
}
str_c[cl_text_dim] ='\0'; // end of the c-string
str2 = str_c; // get the string on the other string type
std::cout << "Dim: " << cl_ text_dim << " C-String var: " << str_c() << " String var << str2 << std::endl;
It is a slow process as passing char by char but it is the only way by the moment I know. Hope it helps. Greetings!

QComboBox findText fails to find QString

Here is my code:
const QString k_NoFilter = "No Filter";
const QString k_Filter1 = "UV filter";
QStringList filters;
filters << k_NoFilter << k_Filter1;
ui.comboFilter->addItems(filters);
int ix = ui.comboFilter->findText(k_NoFilter);
ui.comboFilter->setCurrentIndex(ix);
I can't get the index. It always is -1. What might be wrong?
This is because the string for the item is stored by Qt in a weird way. It is ended with two white spaces (maybe '\r' and '\n').

Peek on QTextStream

I would like to peek the next characters of a QTextStream reading a QFile, in order to create an efficient tokenizer.
However, I don't find any satisfying solution to do so.
QFile f("test.txt");
f.open(QIODevice::WriteOnly);
f.write("Hello world\nHello universe\n");
f.close();
f.open(QIODevice::ReadOnly);
QTextStream s(&f);
int i = 0;
while (!s.atEnd()) {
++i;
qDebug() << "Peek" << i << s.device()->peek(3);
QString v;
s >> v;
qDebug() << "Word" << i << v;
}
Gives the following output:
Peek 1 "Hel" # it works only the first time
Word 1 "Hello"
Peek 2 ""
Word 2 "world"
Peek 3 ""
Word 3 "Hello"
Peek 4 ""
Word 4 "universe"
Peek 5 ""
Word 5 ""
I tried several implementations, also with QTextStream::pos() and QTextStream::seek(). It works better, but pos() is buggy (returns -1 when the file is too big).
Does anyone have a solution to this recurrent problem? Thank you in advance.
You peek from QIODevice, but then you read from QTextStream, that's why peek works only once. Try this:
while (!s.atEnd()) {
++i;
qDebug() << "Peek" << i << s.device()->peek(3);
QByteArray v = s.device()->readLine ();
qDebug() << "Word" << i << v;
}
Unfortunately, QIODevice does not support reading single words, so you would have to do it yourself with a combination of peak and read.
Try disable QTextStream::autoDetectUnicode. This may read device ahead to perform detection and cause your problem.
Set also a codec just in case.
Add to the logs s.device()->pos() and s.device()->bytesAvailable() to verify that.
I've check QTextStream code. It looks like it always caches as much data as possible and there is no way to disable this behavior. I was expecting that it will use peek on device, but it only reads in greedy way. Bottom line is that you can't use QTextStream and peak device at the same time.

Qt XQuery into a QStringList

I'm trying to use QtXmlQuery to extract some data from XML. I'd like to put this into a QStringList. I try the following:
QByteArray in = "this is where my xml lives";
QBuffer received;
received.setData(in);
received.open(QIODevice::ReadOnly);
QXmlQuery query;
query.bindVariable("data", &received);
query.setQuery(NAMESPACE //contains definition of the t namespace
"doc($data)//t:service/t:serviceID/text()");
QBuffer outb;
outb.open(QIODevice::ReadWrite);
QXmlSerializer s(query, &outb);
query.evaluateTo(&s);
qDebug() << "buffer" << outb.data(); //This works perfectly!
QStringList * queryResult = new QStringList();
query.evaluateTo(queryResult);
qDebug() << "string list" << *queryResult; //This gives me no output!
As you can see, everything works fine when I send the output into a QBuffer via a QXmlSerializer... but I get nothing when I try to use a QStringList.
Try to use string() instead of text(), it should work.

Resources