how to implement the macros SIGNAL and SLOT as functions QT - c++

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.

Related

Scope of variables in Qt vs vanilla c++

Disclaimer: I am total newbie to Qt.
Let's assume we have a byte array returned from a function innerFunc that is later used in another function outerFunc.
QByteArray innerFunc(){
QProcess ls;
ls.start("ls", QStringList() << "-1");
return ls.readAll();
}
void outerFunc(){
QByteArray gotcha = innerFunc();
.
.
.
}
In vanilla c++ I would expect readAll function to return a pointer that needs to be deleted later. In Qt this function returns an instance of the QByteArray class so I guess it shouldn't be accessed outside of the innerFunc's scope.
If so, how should I properly transfer the data to an outer function? Should it copied to QByteArray *tmp = new QByteArray or is it unnecessary?
The code you have looks fine. QByteArray is like std::vector<uint8_t> or std::string and not like a pointer. It manages its own memory. It's fine to return it from a function or pass it to a function by value. The compiler will take care of copying and/or moving the data from one object to another as appropriate, using the contructors/operators defined by the QByteArray class.
QByteArray header file
QByteArray documentation

How to pass a function pointer to a method so that it can be used in Qt's connect()?

Background: I want to dynamically create the structure of a context menu and pass the slot of the action items to the method that creates the context menu.
The actual slot is in a QWidget class. I have tried different solutions by passing a function pointer. But they don't compile. Typical error message: "cannot initialize a parameter of type 'void (*)()' with an rvalue of type 'void (TextEdit::*)()'"
This compiles, but does not trigger the desired event:
MenuBuilder builder(&parentMenu);
auto *subMenu = builder.createMenu(SECTION, this, SLOT(TextEdit::onInsertChars()));
And the corresponding method:
QMenu *MenuBuilder::createMenu(const MenuDescription &menuDescription,
const QObject *receiver, const char *target) {
...
inlineMenu->addAction(text, receiver, target);
...
}
I'm sure there's an obvious solution, but I can't figure it out.
The solution: In this context you have to pass SLOT(onInsertChars()) instead of SLOT(TextEdit::onInsertChars()).
auto *subMenu = builder.createMenu(SECTION, this, SLOT(TextEdit::onInsertChars()));
The above should be:
auto *subMenu = builder.createMenu(SECTION, pointerToTheTextEdit, SLOT(onInsertChars()));
(of course if the onInsertChars() method is a slot in the class whose method is making the above call, then you can pass this as the pointer to the object that has the onInsertChars() slot)
Also, you may want to rename const char * slot in your createMenu() function to something else, as Qt's MOC preprocessor has kind of claimed the word slot for its own purposes and that might cause problems for you if you try to use it as a parameter name. Maybe rename the parameter to const char * slotName or something instead.

QString variable changed to QCharRef when i use pointers in method

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

Qt I want to encode a pointer as a string and decode it later

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);

Can't use QString in a QLineEdit nor QComboBox as a parameter

I'm trying to make a function that replace the text inside a QLineEdit when the user want to revert is name to default using a QPushButton.
This is where the code is getting "saved".
`//Must get information in the DB
lineditPlayerName = new QLineEdit("Nouveau Profil");
nameAsDefault = new QString(lineditPlayerName->text());
languageAsDefault = new QString(comboBoxlanguage->currentText());`
This is the function i use to change the value back to default
//This code works
void ProfileManager::revertName(){
lineditPlayerName->setText("nameAsDefault");
btnRevertName->setEnabled(false);
}
But I need it like this :
//This code does'nt
void ProfileManager::revertName(){
lineditPlayerName->setText(NameAsDefault);
btnRevertName->setEnabled(false);
}
I can't get it to work it give's me this error:
no matching function for call to 'QLineEdit::setText(QString*&)'
Thanks
You must dereference the NameAsDefault variable
void ProfileManager::revertName(){
lineditPlayerName->setText(*NameAsDefault);
// ^ Here I dereferenced the pointer
btnRevertName->setEnabled(false);
}
The type of nameAsDefault is pointer to a QString. However QLineEdit::setText expects a QString object, not a pointer. Therefore the compiler tells you that there is no function which expects a pointer.
I did not see your declaration of the nameAsDefault variable, but since
nameAsDefault = new QString(lineditPlayerName->text());
compiles and new returns a pointer, I suppose it is a pointer.
Also, what is probably more important is that you should almost never allocate objects using new. Especially not objects from the Qt library, which are implicitly shared.