Qt sending data from parent to child widget - qt

I have a 2 widgets inherited from QDialog. One of these widgets is called by another widget.
I need to pass data from the parent widget to the child. For example, I want passing QStringList.
I can make signals and slots in both classes. Slot of parent widget class - transferList(QStringList) - filling my QStringList.
How should I make the signal and slot connection? The child widget, of course, knows nothing about the parent.
// .h-file of parent widget.
class ElectricIndicationDialog : public QDialog {
#include "PollIndication.h" // class of child widget
QSharedPointer <PollIndication> pollInd;
public slots:
void transferList(QStringList);
signals:
void listTfansfer(QStringList);
private:
QStringList sendList;
};
// .cpp-file of parent widget
pollInd = QSharedPointer <PollIndication>(new PollIndication());
pollInd->show();
void ConfIndication::transferList(QStringList lst) {
lst.append("str1");
lst.append("str2");
}
// .h-file of child widget
class PollIndication : public QDialog {
public slots:
void getList(QStringList);
signals:
void listGet(QStringList);
private:
QStringList recList; // We transfer data to it
}

You don't need a signal/slot for that: your parent knows the type of its child and has a pointer on it. So, you can call a method of PollIndication when you need to send data to your dialog.
void ConfIndication::transferList(QStringList lst) {
lst.append("str1");
lst.append("str2");
pollInd->changeTransferList(lst);
}
If your dialog is modal, you can also create your dialog only when needed and give your list as parameter of the constructor.
void ConfIndication::transferList(QStringList lst) {
lst.append("str1");
lst.append("str2");
PollIndication* pollInd = new PollIndication(lst, this);
pollInd->exec();
}

It is normally a bad idea to make a parent class to know what are their children....
you can in the parent class define an abstract method (think about some pure virtual) so every childclass is forced to implement it... after that, the parent class can invoke the method and the child will implement the login depending on how it must react to it...

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

Is it feasible to use decorator pattern with QWidget?

According to wikipedia, I need to
In the Decorator class, redirect all "Component" methods to the
"Component" pointer;
But QWidget has too many methods to redirect.
For example I want to create a moveable widget decorator:
class Moveable : public QWidget
{
Q_OBJECT
public:
explicit Moveable(QWidget * widgetToBeDecorated){
this->widgetToBeDecorated = widgetToBeDecorated;
}
~Moveable();
protected:
void mousePressEvent(QMouseEvent* e) override {
lastPoint = e->pos();
widgetToBeDecorated->mousePressEvent(e);
}
void mouseMoveEvent(QMouseEvent* e) override {
auto offset = e->pos()-lastPoint;
lastPoint = e->pos();
widgetToBeDecorated->move(widgetToBeDecorated->pos()+offset);
widgetToBeDecorated->mouseMoveEvent(e);
}
void mouseReleaseEvent(QMouseEvent* e) override {
widgetToBeDecorated->mouseReleaseEvent(e);
}
private:
QWidget* widgetToBeDecorated;
QPoint lastPoint;
};
Do I need to redirect other methods like show(), paintEvent(QPaintEvent*)?
The decorator pattern is a guideline, not a rule. You are fully allowed to modify patterns that do not suit your purposes. In this case, you only need to concern yourself with the part of QWidget that are involved with positioning, so there is no advantage to overriding any other of it's methods.
It looks like you only want to modify the behaviour of certain events in your QWidget. Lucky for you, there is already a mechanism in QObject to do just such a thing, it's called an Event Filter.
There is a nice example of how to use it in the Qt documentation, and a good advantage that improves on your class above is that you can use the same object to filter many QWidgets, instead of having one filter for each widget.

create object for class inheriting QLayout

I have a screen class as
class Screen : public QLayout
{
public:
Screen();
~Screen();
void paintEvent(QPaintEvent *e);
};
When I am creating the object I got an error that can not create an object for pure abstract class. Since QLayoput is pure abstract , How can I create an object for a class which is inherits the QLayout ?
definitions:
Screen::Screen( )
{
}
Screen::~Screen()
{
delete this ;
//Screen(new QSize (100,100));
}
void Screen::paintEvent(QPaintEvent *e)
{
}
QLayout is pure abstract, meaning it has virtual members without a definition. To subclass it, you need to provide definitions for all such methods in your class. Specifically, Qt Docs state that
To make your own layout manager, implement the functions addItem(),
sizeHint(), setGeometry(), itemAt() and takeAt().
For more, see there (there are additional optional advices for further functions which should be implemented): http://qt-project.org/doc/qt-4.8/qlayout.html

Qt - Saving a custom QGraphicsScene with custom QGraphicsItems

I created a public QGraphicsItem Node class which has getter/setter methods for a bunch of properties relevant to my application. The application is a diagram editor in which the users design models. This Node class is used to populate an also public QGraphicsScene Diagram class.
I'm now trying to implement a load/save mechanism in the app that enables users to save and reuse the models - editing them as they were when they saved. I'm having some trouble figuring out how to attack this problem.
I already know I have to get the relevant properties for the QGraphicsItem objects and save those to file, and then on load, reconstruct the scene using the data I saved. My question is: when I use the QGraphicsScene::items() function, it returns a QList<QGraphicsItem *>. What can I do to have it return a QList<Node *>?
If I get a list of all the nodes I appended to the scene, I know what to do next.
I began to realise that I will probably have to reimplement the items() function in my Diagram class, but I was hoping I could get away with it more easily. In this case, can someone please explain how to do it?
I would suggest to implement the QGraphicsItem::type() method and using qgraphicsitem_cast to cast into the desired class. In your case, you could subclass all your custom GraphicsItems from a common base class.
Your base class would look like this:
class MyGraphicsItem: public QGraphicsItem
{
enum { Type = UserType + 1 };
int type() const { return Type; }
};
Your Node and your Link class would inherit this base:
class Node : public MyGraphicsItem
{
// ...
};
class Link : public MyGraphicsItem
{
// ...
};
Somewhere else you could cast a QGraphicsItem into your base class MyGraphicsItem like this for example:
QList<QGraphicsItem*> allItems = graphicsScene->items();
foreach (QGraphicsItem *item, allItems) {
// Using qgraphicsitem_cast
MyGraphicsItem* graphicsItem = qgraphicsitem_cast<MyGraphicsItem*>(item);
if (graphicsItem) {
// Do something with MyGraphicsItem
}
}
While the items function returns a list of QGraphicsItem pointers, you could try either dynamic_casting to check if it's a Node pointer or use the Qt metadata and the type() function.
However, the method I often use, which can help you in other ways too, is to maintain a unique id for every type of object and a static lists of item Ids. For example: -
class BaseItem : public QGraphicsItem
{
public:
BaseItem(QGraphicsItem* parent)
: QGraphicsItem(parent), m_Id(m_NextId++) // initialising the object's unique Id
{
}
unsigned int ID() const
{
return m_Id;
}
private:
static unsigned int m_NextId; // the next Object Id, initialised to 0 in implementation
unsigned int m_Id; // the object's unique Id
}
class Node : public BaseItem
{
public:
Node(QGrahicsItem* parent)
: BaseItem(parent)
{
m_NodesList.push_back(m_Id);
}
private:
static QList<unsigned int> m_sNodesList; // all Node ids in the scene
QList<unsigned int> m_linkedNodeList; // linked nodes
}
All items added to the GraphicsScene are inherited from the BaseItem
You also have a static list of Node Ids, so you can iterate through all of them for loading / saving and you can add a static helper function in the base class to return a list of Nodes, by searching through the List of Node Ids and matching them to their node pointers in the scene.
This architecture also allows you to include a list of linked node ids in each Node object, rather than using the parent / child system of Qt, which in the case of a node diagram, isn't always what is needed.
Overall, I've used this architecture for many QGraphicsScene applications and it has really made development very easy for items that have complex links to other items.

Resources