I am working on a module in which GUI and back-end interact by message passing.
I initialised a char* as nullptr. GUI takes a QStringList which is tokenized. I cannot do the changes in the tokenized list. I receive a "(null)" in the list. Now I feel like by comparing to "(null)" is not the way to go. Is there any initialisation for char* which would be taken as an empty string by QString?
Use an empty string when constructing a QString when the pointer is NULL.
QString obj = (ptr == nullptr? QString("") : QString(ptr));
And then use obj.
Not sure to understand what you want but if i am not mistaken :
char *c = nullptr;
QString str(c);
str.isEmpty(); // return true
Related
Hello everyone I am trying to get to know pointers better and I stumbled into a Qt type change. I have made a QString array and gave the pointer to the array to a method. But when I try to use a QString functions it give a error and says that it is a QCharRef which does not have the member function isEmpty().
The code:
QString data_array[2][3] =
{
{"11:28:8","Room 1","Presence detected"},
{"11:38:8","Room 1","No presence"}
}
bool method(QString *_data_array)
{
QString *data_array = _data_array;
return data_array[0][1].isEmpty(); /* changed to QCharRef */
}
My question is why does this happen and how can I prevent it or change it?
The reason for which you are getting QCharRef is due to how QString is built. The [] operator returns one character from a QString (QString is built up from QChars, much like strings in C/C++ are character arrays). From the Qt documentation:
The return value is of type QCharRef, a helper class for QString. When you get an object of type QCharRef, you can use it as if it were a QChar &. If you assign to it, the assignment will apply to the character in the QString from which you got the reference.
So what that means for you is that when you use the lovely square bracket operators, you are no longer using a QString, you are using a QChar reference.
As for how to change it, QChar's isNull() seems like it would fit your uses. so instead try return data_array[0][1].isNull(); and that should work.
I would also look into QStringList if you're doing things with lists of strings
In my Qt app I'd like to encode a pointer to an object as a string, pass it to another bit of code then decode it so that I can access the object.
This is part of internal drag and drop with a QTreeView. In my mimeData() method I have:
QMimeData * TreeModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
foreach (QModelIndex index, indexes)
{
QString colText;
if (index.isValid()) {
TreeItem *item = getItem(index);
// grab the text from each column
for(int cc=0; cc < item->columnCount(); cc++ ) {
colText = item->data(cc).toString();
stream << colText;
}
// add the pointer to the item
qDebug() << quint64(&item);
stream << quint64(&item);
}
}
mimeData->setData("application/vnd.text.list", encodedData);
return mimeData;
}
The qDebug() line produces a number like 140736277471632 which could be right, but is probably wrong.
How should I encode a pointer as a string so that it can be fed into a stream. And how should I then decode it and get the pointer to the original object?
Thank you.
I would dis-advice doing this.
Serializing objects in strings and de-serializing later makes sense for "moving" objects from one process to another. But within one process, you should pass pointers directly, or wrapped in a container like shared-pointer.
If the only way to pass something is a string, create an instance (e.g. QMap<QString, YourPointerType>) where you can register a pointer and access it by a string-name.
If you wrap this map in a class, you can check, if this pointer already exists while registering and if it still exists while retrieving.
Besides, in a models you can store anything you want using User-Roles. You are not limited to store your custom data as mime data.
Here you don't want to take the address of item, but its value. It's a pointer, its value is the address you're looking for, not its address (which, as already mentioned, is completely irrelevant and dangerous to manipulate once the if block scope is exited).
qDebug << qint64(&item);// will print the address this pointer is stored at.
qDebug << qint64(item);// will print the address this pointer is pointing at
EDIT: If you want to get the address back from a string into a pointer, read it as a number from a stringstream, i.e.:
std::istringstream is{str};
long pointer;//be careful with the size of a pointer in your case.
is >> pointer;
TreeItem* item = reinterpret_cast<TreeItem*>(q);
Details:
Im using this github project to convert a Json to an object.
https://github.com/ereilin/qt-json
With this json:
{
"bin": "/home/pablo/milaoserver/compile/Devices01.olk",
"temp":"/home/pablo/milaoserver/temporal/",
"port": "1234",
"name": "lekta",
}
with this two lines I create two char pointers:
char* bin = configuration["bin"].toString().toLatin1().data();
char* temp = configuration["temp"].toString().toLatin1().data();
Debugging the app I have the proper strings.
However when I use them, concretely the "bin" char changes to
`hom
Any Idea?
SOLUTION IN COMMENTS:
The problem was the "persistence" of the data.
I found the solution with:
std::string binAux(configuration["bin"].toString().toLatin1().data());
std::string tempAux(configuration["temp"].toString().toLatin1().data());
char* bin = new char[binAux.size()+1] ;
strcpy(bin, binAux.c_str());
char* temp = new char[tempAux.size()+1] ;
strcpy(temp, tempAux.c_str());
Your error here is because of temporary object.
toString() create a temporary object no longer available after the semicolon.
The standard state :
12.2 Temporary objects [class.temporary]
3/ [...] Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.
That is, when you want to access it you have Undefined Behavior.
This should solve your problem :
QString str = configuration["bin"].toString().toLatin1();
QByteArray ba = str1.toLatin1();
char *bin = ba.data();
But what do you want to use char* ? You are in C++, use std::string or Qstring instead :
#include <string>
std::string bin(configuration["bin"].toString().toLatin1().data());
Can you please try something like
std::string sbin(configuration["bin"].toString().toLatin1().data());
std::string sTemp(configuration["temp"].toString().toLatin1().data());
toString() creates a QString object that is deleted immediately, so the data that is contained in it will be freed. I do recommend you to store the data in a QString until you use that char* bin.
Your solution could be shorter, like this:
char* bin = strdup(configuration["bin"].toString().toLatin1().data().c_str());
char* temp = strdup(configuration["temp"].toString().toLatin1().data().c_str());
strdup() does virtually all you do.
I made a function which returns a QString. At some points in my function it should return an empty QString.
Just returning "" doesn't work. When I use QString::isEmpty() it's not.
My "emergency plan" was to return an "empty" string and check with it whether the text is "empty". But I don't think that's good style.
So how do I return an empty QString?
The idiomatic way to create an empty QString is using its default constructor, i.e. QString(). QString() creates a string for which both isEmpty() and isNull() return true.
A QString created using the literal "" is empty (isEmpty() returns true) but not null (isNull() returns false).
Both have a size()/length() of 0.
According to the QString docs, returning "" should work; as should returning QString().
Try printing out the string you are testing to make sure it's really empty:
printf("xxx [%s]\n", myStr.toUtf8().constData());
Well, what i want is to implement functions that works like the macros SIGNAL and SLOT but with my own implementation, so the goal is that the function (or my own macro if i can create it) receive a parameter like an String "mycustomsignal" and he return a const char* "2mycustomsignal(double,int)" so i do that using a QMap for store this asociation QMap<"signal name","signal signature">, i fill it in another function.
in this case my QMap is this->signals so i search the signature "mycustomsignal(something)" with the key "mycustomsignal" and prepend the code that QObject::connect recognize for signals and i get "2mycustomsignal(something)" so i convert it in const char* because QObject::connect have this parameters in this format and i want to use also in conjuntion with SIGNAL and SLOT MACROS like this:
QObject::connect(customwidget, customwidget->getSignal("somesignal"),
somewidget, SLOT(someslot()));
the function that i use is (only for undertand what i do):
const char* SomeClass::getSignal(QString signalName) {
QString signalsignature = this->signals.value(signalName);
signalsignature.prepend(QString::number(QSIGNAL_CODE));
QByteArray ba = signalsignature.toLatin1();
return signalformated; //Here is the lost of data because QByteArray only exist in the function
}
but this return a pointer to local and the source of the data is destroyed when the function ends, so how i could do this with a function or creating my own MACRO?
Thanks for any help or suggestion.
You have to return QByteArray from your method, return ba;, then get the const char* from the return value:
QObject::connect(customwidget, customwidget->getSignal("somesignal").constData(),
somewidget, SLOT(someslot()));
If you really want to return char pointer, then you have to keep the QByteArray around, for example by adding it to a QList member variable of the same object, so it will get destructed when the instance gets destructed.