Inherit signals and slots from a base class in Qt - c++

I have created:
class A : public QObject
{
Q_OBJECT
public signals:
Q_SIGNAL void mySignal();
};
And I would like to derive:
class B : public A
{
//Some added functionality
};
And still be able to connect mySignal() emitted by B (which it inherited from A) to a slot in my QMainWindow:
B b;
connect(&b, SIGNAL(mySignal()), this, SLOT(aSlot()));
Currently this method results in "multiple definition of "A::disconnected()" and the compiler points me to the moc file here:
void A::disconnected()
{
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
}
What is the problem here?
I have done my research but what I found seems to be on different types of inheritance patterns and I don't understand Qt enough to port conclusions here.
Edit: I had stupidly forgotten the & in my original post, thanks Scheff's cat - I've updated my problem.

For those of you who have the same problem as this one, check your source file for a potential definition of A::mySignal()... I had created an empty definition of the function, as usual, whereas apparently MOC creates one for us. Resulting in multiple definitions.

Related

Alternatives to Qt Signals and Slots for Inter-Object Communication

What are alternatives to using Qt-like signals and slots for communication between two objects (class instances) in both directions?
I know this can be realized by saving a reference of the other in each object. However, this gets sort of confusing when there are many different objects and all objects are supposed to interact with (and thus to know) one another.
The other question I've had was how Qt signals and slots implement this inter-object communication internally (a simple overview of the internal course of events would be helpful)?
A Qt example of what I'm talking about would be the following. Both objects, c and d, can emit a signal that is connected to a slot of the other.
class Chicken : public QObject
{
Q_OBJECT
public:
Chicken() = default;
public slots:
void helloBackDuck() {
std::cout << "Hello Back Duck" << std::endl;
}
signals:
void helloDuck();
};
class Duck : public QObject
{
Q_OBJECT
public:
Duck() = default;
public slots:
void helloBackChicken() {
std::cout << "Hello Back Chicken" << std::endl;
}
signals:
void helloChicken();
};
int main() {
Chicken c;
Duck d;
connect(&c, &Chicken::helloDuck, &d, &Duck::helloBackChicken);
connect(&d, &Duck::helloChicken, &c, &Chicken::helloBackDuck);
}
Qt Signal and slot mechanism is best choose in Qt programs, but if you want to know about other options, you have these:
You can develop your own Observer structure that would be like Qt signal and slot but you should invent the wheel from the beginning by yourself.
You should create an Observe class and a Subject class. In the beginning connect your Observer by passing a reference of it to Subject and as soon as the condition meet Subject will call the update function of all of the instances (emit).
For more explanation check this link.
Another option is using Boost signal2 that is also similar to Qt signal slot but from third party libraries. Usage is similar to Qt signal.
For more explanation check this.

Exposing internal component of a class in order to prevent writing too much code and impact on performance

Let's say I have a class
class B : public class QObject {
Q_OBJECT
public:
B(QObject* parent=Q_NULLPTR);
signals:
void signalData(int data);
public slots:
void slotGetData();
private:
}
The slotGetData() is triggered externally and basically retrieves some data from somewhere and sends it back using signalData(int data). On the other hand I also have another class
class A : public class QObject {
Q_OBJECT
public:
A(QObject* parent=Q_NULLPTR) {
// Init B, move to thread, setup timer, connect timer's timeout to B's slotGetData()
// Connect B to A
connect(this->B, SIGNAL(signalData(int)), this, SLOT(slotGetData(int)));
}
signals:
// Emit signal containing data to another Qt component
void signalData(int x);
private slots:
// Connect B::signalData(int x) to this slot and re-emit the data using A::signalData(int x). Don't do anything with the data!
void slotGetData(int x);
private:
B* workerObj;
QThread worker;
QTimer workerTimer;
}
which basically is responsible for instantiating workerObj, moving it to worker thread and connecting the workerTimer's timeout() signal to B::slotGetData().
The purpose of this class is to enable proper integration (multi-threaded) of B inside a third-party class that wants to use it for example:
class ThirdParty : public class QWidget {
Q_OBJECT
public:
ThirdParty(QObject* parent=Q_NULLPTR) {
// Init A
// Connect to B through A
connect(this->integrationObj, SIGNAL(signalData(int)), this, SLOT(slotGetData(int)));
}
private slots:
// Connect A::signalData(int x) to this slot and do something with the x (change UI, whatever)
void slotGetData(int x);
private:
A* integrationObj;
}
The class ThirdParty gains indirect access to specific features of B through A.
Now the dilemma I'm facing is the following:
Should I just relay the data signal which comes from B through A and expose it as a signal of A or
Should I just return a const reference to B to allow an class which has A in it (so that it can use B) to directly connect to B's signalData(int x)?
In the first case (which I have) I basically have to mirror every single signal B wants to offer to the outside inside A (by providing the respective private slots in A and also signals that are basically the same as B's). Needless to say this leads to having too much of the same stuff and also has some (even if just slight) performance impact since I get 2 signal emissions (from B to A and then from A to whichever other object has A) and 2 slot calls (one in A to get signal from B and one in whichever other object has A to get signal from A).
The second case seems nice but I fear that I will expose features of B which the class containing A may not be allowed to have access to
If the second case is implemented I would have something like this (B doesn't change):
class A : public class QObject {
Q_OBJECT
public:
A(QObject* parent=Q_NULLPTR);
const B* getB() const; // Return a reference to B that cannot be changed but can be used to expose B's slots and signals
signals:
private slots:
private:
B* workerObj;
QThread worker;
QTimer workerTimer;
}
class ThirdParty : public class QWidget {
Q_OBJECT
public:
ThirdParty(QObject* parent=Q_NULLPTR) {
// Init A
// Connect to B directly!
connect(this->A->getB(), SIGNAL(signalData(int)), this, SLOT(slotGetData(int)));
}
private slots:
// Connect B::signalData(int x) to this slot and do something with the x (change UI, whatever)
void slotGetData(int x);
private:
A* integrationObj;
}
What should I do here? Sadly there are no private signals hence all B signals but also all of its public slots will be exposed. If all these are to be used, there is no issue with this degree of exposure but otherwise...not so much.
facepalm I already had the solution in another project of mine. :D I just need to provide a connectTo(QObject* thirdparty) inside A, which internally connects the thirdparty slot only to specific signal of B thus not exposing things from B that are not meant to be exposed!
Another better solution is to use a signal-to-signal connection (connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type)) or use the child-parent relation though in the latter I have to make sure that the parent actually is set. This is also known as signal forwarding and requires 2 signals but no extra slots. Since A is visible to ThirdParty I can do (this here represents ThirdParty) connect(this, SIGNAL(signalFromThirdPartyToB()), this->a, SIGNAL(signalFromAToB())) to set the forwarding of ThirdParty signals to B through A and then do the actual signal-slot connection between the forwarding signal in A to a slot in B by calling (this here represents A) connect(this, SIGNAL(signalFromAToB()), this->b, SLOT(slotB())).

Compiler recognizing wrong function with same name

Im implementing a new slot which just has to call the method reset(). My new class is subclassing QAbstractListModel in which QAbstractListModel::reset() exists.
//stationlist.h
class StationListModel : public QAbstractListModel
{
Q_OBJECT
...
public slots:
void dataChanged();
//stationlist.cpp
...
void StationListModel::dataChanged()
{
reset();
}
However, in the implementation the method reset() is recognized as QTextStream::reset() and doesn't compile because of this. What could be the cause for such behaviour?
Thanks to the comment, the conclusion is that the method QAbstractListModel::reset() doesn't exist.
It is here only still available fer backwards compatibility http://qt-project.org/doc/qt-5.1/qtcore/qabstractitemmodel-compat.html#reset.
I believe that QTextStream::reset() is just something that the QtCreator offered as a global autocomplete.
The solution is to use non deprecated method.

Object::connect: No such signal when obj is returned as shared_ptr

Using Qt's signal & slot, I get error:
Object::connect: No such signal FvOverlayPolygon::mouseHoveredOnElemSig(rf::AbstractFvOverlay*)
My other connects work fine and I've checked everything I can think of (refered to 20 ways to debug Qt signals and slots too). Because I personally for the first time use shared_ptr for Qt for this sample, I suspect there might be something wrong in how I use shared_ptr. I really appreciate your opinions.
concreteFvOverlay.cpp
#include "rf_common/abstractFvOverlay.h"
void FvScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
rf::AbstractFvOverlay::Ptr item_overlay;
item_overlay = this->createOverlay(myItemMenu, &pixmap_overlay); // this inherits Class A
bool con1 = connect(item_overlay.get(), SIGNAL(mouseHoveredOnElemSig(rf::AbstractFvOverlay*)), this, SLOT(mouseHoveredOnElem(rf::AbstractFvOverlay*)));
}
}
This overlay is instantiated in this:
abstractFvOverlay.cpp
boost::shared_ptr<rf::AbstractFvOverlay> FvPolygonScene::createOverlay(QMenu *menu, QPixmap *pixmap_overlay)
{
return boost::shared_ptr<rf::AbstractFvOverlay>(new FvOverlayPolygon(menu, *pixmap_overlay));
}
overlay.h
#include <QGraphicsItem>
#include <boost/shared_ptr.hpp>
class AbstractFvOverlay : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
AbstractFvOverlay(QMenu *contextMenu, QGraphicsItem *parent, QGraphicsScene *scene);
virtual ~AbstractFvOverlay();
typedef boost::shared_ptr<AbstractFvOverlay> Ptr;
signals:
void mouseHoveredOnElemSig(AbstractFvOverlay *i);
For your interest, the reason I use shared_ptr here is I want to do interface-based programming (not sure if this is an official way to call this style but what I mean is defining behavior in abstract classes and only for some behaviors I describe them in concrete classes, which Java allow).
You must use full scope names of types in signal declaration even if you're in same scope. Replace signal void mouseHoveredOnElemSig(AbstractFvOverlay *i); with void mouseHoveredOnElemSig(rf::AbstractFvOverlay *i); or use AbstractFvOverlay without scope in your connect.

Qt 4.0 Signals and Slots with minimal OOP

I'm relatively new to Qt; I'm writing a small program and I don't want to get into making my own classes for each widget and such. So far I haven't had many difficulties, but I'm slightly confused about signals and slots. I want to make a signal that triggers when a user types into a text box (QLineEdit) and presses enter. I would prefer the slot to be a function that accepts the text inputted by the user.
So far I've come up with this:
textBox.connect(&textBox,SIGNAL(textBox.returnPressed()),/*What to put here?*/,processText(/*Here?*/))
I apologize if this piece of code is terribly wrong; as I said I'm relatively new to Qt.
Help would be very much appreciated.
Signals and slots must be methods of a QObject (/QObject subclass). You can't use free functions as slots. "Minimal OOP" here probably would mean QObject singleton(s) containing the slots.
Also a signal with signature (A, B, C) can only be connected to slots with signatures (), (A), (A, B), (A, B, C), i.e. one can discard/ignore trailing arguments. A slot cannot have more/other arguments than the signal, nor can you bind slot arguments to a certain value when connecting (Where QSignalMapper covers the most common use case I think).
Sadly, I don't think there is a way to achieve this without inheritance - if you want the text to go with the signal or some custom handling to be done in the slot that is called.
If not, you can just use the "returnPressed" signal emitted from the QLineEdit and some pre-existing slot I couldn't possibly know.
Here's my solution using inheritance.
To make your own slot, you need to make an inherited class. Inherit it from Qobject, directly or indirectly.
//myClass.h
#ifndef myclass_h_
#define myclass_h_
#include <QObject>
class myClass: public QObject
{
// important
Q_OBJECT;
....
public slots:
void takeText(QString p_value);
};
#endif
And to get a signal like that from a QLineEdit, you need something custom as well
//myLineEdit.h
#ifndef mylineedit_h_
#define mylineedit_h_
#include <QLineEdit>
class myLineEdit: public QLineEdit
{
// important
Q_OBJECT;
....
public slots:
void handleReturnPressed();
signals:
void newText(QString p_value);
};
#endif
And then do these
myLineEdit::myLineEdit()
{
connect(this, returnPressed(),
this, handleReturnPressed());
}
void myLineEdit::handleReturnPressed()
{
emit(newText(text());
}
After this, create a myClass object, and connect the signal to it.
myClass * thing = new myClass();
myLineEdit* lineEdit = new myLineEdit();
connect(lineEdit, SIGNAL(newText(QString),
things, SLOT(takeText(QString));