QT using public slot of another class - qt

I have a class ArrayToolBar which has a public member commandBox and a public function createArray().
class ArrayToolBar : public QToolBar
{
Q_OBJECT
public:
explicit ArrayToolBar(const QString &title, QWidget *parent);
CommandBox* commandBox = new CommandBox();
void createArray();
Here is how createArray() is defined
void ArrayToolBar::createArray(){
commandBox->setFocus();
connect(commandBox, SIGNAL(returnPressed()), this, SLOT(commandBox->SubmitCommand()));
}
SubmitCommand() is a public slot in CommandBox class.
My problem is that I am getting an error : No such slot exists.
Is this because I have used a slot of some other class in ArrayToolBar? Is there a way around?

You can use new connection syntax with labmda expressions.
Qt has a good aricle about it. https://wiki.qt.io/New_Signal_Slot_Syntax
And final code will looks like this:
connect(commandBox, &CommandBox::returnPressed,
this, [=] () {commandBox->SubmitCommand();});

You can use lambda expressions like already mentioned.
But this should do what you want without lambda:
connect(commandBox, SIGNAL(returnPressed()), commandBox, SLOT(SubmitCommand()))

Related

QObject connect fails in Qt

everyone!
I am having a problem using QObject::connect with some custom classes I've created. First of all, I have created 2 classes that inherit from QObject, they are called: Valve and PushButton. They are instantiated inside controllers called PanelController and SynopticController, which are also QObjects. And these controllers are instantiated inside another class called MasterController, also a QObject. I find this information useful since I think it is a problem of referencing the classes or the way I might be instantiating my classes inside these controllers. I strongly think this, because in my main method, when I do the following snippet of code, the connection works:
...
avionics::synoptic::Valve valveTest(nullptr, avionics::synoptic::ValveName::ABV);
avionics::panel::PushButton pushButtonTest(nullptr, avionics::panel::PanelNames::RECIRC);
QObject::connect(&pushButtonTest, &avionics::panel::PushButton::onStateColorChanged, &valveTest, &avionics::synoptic::Valve::updateState);
...
Basically, the controller classes are:
// MasterController
class MasterController : public QObject {
...
private:
panel::PanelController* panelController{nullptr};
synoptic::SynopticController* synopticController{nullptr};
}
// Panel Controller
class PanelController : public QObject {
...
explicit PanelController(QObject *parent = nulptr){
this->pushButtons.append(new avionics::panel::PushButton(_panelController, avionics::panel::PanelNames::RECIRC));
}
private:
QList<avionics::panel::PushButton*> pushButtons{};
}
// SynopticController
class SynopticController : public QObject {
private:
QList<avionics::synoptic::Valve*> iceValves{};
explicit SynopticController(QObject *parent = nullptr) {
antiIcePneumaticLines.append(new avionics::synoptic::PneumaticLine(_synopticController, avionics::synoptic::PneumaticLineName::APU_2_ABV));
}
}
My problem is that when I do the same call for the QObject::connect either from my MasterController constructor or my main method, the signal doesn't call the slot function. I want to connect pushButtons to valves, and to do this I am using getters from my controllers. The call to QObject::connect that doesn't work is:
QObject::connect(panelController->getpushButtons().at(1), &avionics::panel::PushButton::onStateColorChanged, synopticController->getValves().at(1), &avionics::synoptic::Valve::updateState);
// Example of getter
QList<avionics::panel::PushButton*> PanelController::getPushButtons(){
return pushButtons;
}
I've put some prints inside the method that emits the signal and tried debugging it, but the signal is emitted and the slot isn't called. The classes return from the getters are not undefined or null, I've checked it. Let me know if something wasn't clear. Thanks in advance!

QT permission member between classes

I would like to send a member parentWidget, definited in a class function, to another class by a connection because I want to to add it in a list.
Unfornately I have got a error with this member permissions.
The respond error is:
C2248: 'QGraphicsWidget::QGraphicsWidget': cannot access private member declared in class 'QGraphicsWidget'
So here is my function
void DiagramScene::insertWidget(DiagramItem::DiagramType diagramtype)
{
QGraphicsWidget parentWidget;
//some code
connect(this,SIGNAL(sendToItemList(QGraphicsWidget)),diagramitem,SLOT(addToItemList(QGraphicsWidget)));
emit this->sendToItemList(parentWidget);
}
and this is my slot:
void DiagramItem::addToItemList(QGraphicsWidget widget)
{
QGraphicsWidget * newWidget;
memmove(newWidget,&widget,sizeof(QGraphicsWidget));
items.append(newWidget);
}
QGraphicsWidget inherits QObject, so it is uncopyable. The addToItemList function receives its argument by value, which leads to a copy attempt. One possible solution is to change the function's argument type to QGraphicsWidget* and create the object as QGraphicsWidget *parentWidget = new QGraphicsWidget(). This would also eliminate a very strange and incorrect use of memmove from your code.
I might be wrong but as far as I know you can't copy QGraphicsWidget since it inherits from QObject. (Can be read here)
My suggestion:
void DiagramScene::insertWidget(DiagramItem::DiagramType diagramtype)
{
QGraphicsWidget* parentWidget = new QGraphicsWidget();
//some code
connect(this,SIGNAL(sendToItemList(QGraphicsWidget)),diagramitem,SLOT(addToItemList(QGraphicsWidget)));
emit this->sendToItemList(parentWidget);
}
void DiagramItem::addToItemList(QGraphicsWidget* widget)
{
items.append(widget);
}

Qt, "no such signal" runtime error from child class, having Q_OBJECT macro

Using Qt 5.4, I'm having trouble with a signal emitted from a child class. This is the situation:
There is a
class Player : public QDialog{
Q_OBJECT
/*...*/
public slots:
void ReactToAdapter(Adapter::state_t newState);
private:
Adapter* adapter;
}
The
class Adapter : public QObject{
Q_OBJECT
public:
enum state_t {/*...*/}
signals:
void StateChagned(state_t newState);
}
is purely virtual. One of its Implementations is given as
class AdapterCAN : public Adapter{
O_OBJECT
/*...*/
}
AdapterCAN is emitting the StateChagnedwithin one of its methodes.
state_t is visible everywhere through includes. All three classes have the Q_OBJECT macro.
When I try to do
Player::ConnectToCANBus(/*...*/){
adapter = new AdapterCAN(/*...*/);
connect(adapter, SIGNAL(StateChanged(Adapter::state_t),
this, SLOT(ReactToAdapter(Adapter::state_t));
}
This creates the error message
QObject::connect: No such signal AdapterCAN::StateChanged(Adapter::state_t) in ..\player.cpp:90 during runtime.
It looks like the signal is not inherited!? Anyone having any ideas what I might be doing wrong? Thanks!
Changing the definition of the signal to
class Adapter : public QObject{
/*...*/
void StateChagned(state_t);
}
solved it. The qualified name has to be left out.
Thanks to #vahancho for pointing this out!
If anyone finds here, please check your connect function for errors. I once wrote such a stupid error, but the compiler did not give any error report.
connect(m_pInitEncFromDvd1, SIGNAL(signalFinish(int,QStirng)),
this, SLOT(slotDVD1InitFinish(int,QString)),
(Qt::ConnectionType)(Qt::ConnectionType::AutoConnection | Qt::ConnectionType::UniqueConnection));
Pay attention to
"SIGNAL(signalFinish(int,QStirng))"
, I accidentally write QString as QStirng, and it works perfectly after correction.

Derive UIC generated Qt UI class from custom interface

I've a simple Qt Question. I want that automatically generated UIC files are derived from a custom interface class like in:
Intention
class MyUiInterface {
public:
virtual void setupUi(QWidget* w) = 0;
virtual void retranslateUi(QWidget*w) = 0;
};
Generated UIC file should look like:
class Ui_MyWidget {
public:
void setupUi(QWidget* w) {
...
}
void retranslateUi(QWidget* w) {
...
}
};
namespace Ui {
class MyWidget : public MyUiInterface , public Ui_MyWidget {};
}
Why?
Every Ui::Class would then implement MyUiInterface. In each class that derives from Ui::Class (see The Multiple Inheritance Approach) I would be able to call setupUi and retranslateUi which makes sense if the class that derives from UI::Class class is a base class either. I want every widget to be derived from my abstrcat base class MyWidgetBase. Consider following:
class MyWidgetBase abstract : public QWidget, protected MyUiInterface {
protected:
void changeEvent(QEvent *e) {
QWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
retranslateUi(this); // Still abstract here
}
}
};
class MyWidget : public MyWidgetBase : public Ui::MyWidget {
};
The effect is, every time MyWidget::changeEvent() is callled, retranslateUi of that specific class is called. Otherwise changeEvent had to be reimplemented in each class. This would be a bit against "code reuse" concept.
I think Qt UIC is not able to handle this situation isn't it? Is there a similar way to solve this problem?
Unfortunately, reading XML Schema for ui files is telling us that this is not possible to automate using uic compiler.
However, it is unclear to me why you would want to implement that automatically - even if the Uic somehow manages to implement your interface, you will still need to add bodies of the functions by hand, editing generated .h file, as I am sure that there is no way to include custom code in xml file which will translate as C++ code.
Why you just don't reimplement setupUi and retranslateUi in your MyWidget class? Every Ui class will have one of these classes, so you can implement this on this level, instead of base class. It is possible that I am missing something, but I see this as an appropriate way to do this.
class MyWidget : public MyWidgetBase, public Ui::MyWidget {
public:
void setupUi(QWidget* w) {
...
}
void retranslateUi(QWidget* w) {
...
}
};
With this approach, you don't need to reimplement changeEvent() in any of your custom widgets, and changeEvent will still call the appropriate retranslateUi().

Is it possible to emit a signal from the baseclass of a derived object using "this"

Not too sure how to formulate my question and I hope that this is more clear. I want to have a baseclass that looks something like this:
class Base : public QObject {
Q_OBJECT
void doSomething() { emit test(this); }
virtual void doSomethingElse() = 0;
signals:
void test(Base*);
}
And then in the derived class do this:
class Derived : public Base {
void doSomethingElse() { emit test(this); }
}
If I now listen to the signals of this object and do I listen to test(Derived*) or/and test(Base*)?
The moc generates at compile time a list of the slots and signals based on the way you declared them in the classes that use the Q_OBJECT macro.
This list is a list of strings, so if you declared:
signals:
void test(Base*);
the item in the list would be the string "test(Base*)" (you can see that list in the variable qt_meta_YourClass of the file moc_yourclass.cpp in the output directory).
The macros SIGNAL and SLOT also return strings, connect() canonize them so they are formatted like the one from the moc generated list, and compares them to those in that list.
When you derive the class, the string hasn't changed, so you still have to use SIGNAL(test(Base*)).
You shouldn't include senders as parameters of signals. You can simply use QObject::sender() to get the QObject that has sent the signal.
eg:
emit test();
Then in a slot:
void Listener::someObject_test() {
QObject* sender = QObject::sender();
// or:
Derived* sender = (Derived*)QObject::sender();
}
As the derived class does not have its own signal, you will listen the test(Base*).

Resources