0

I have an application with multiple "input widgets" written as inpependent classes, that all store a shared pointer of the respective class that's data thay show. In each of these widgets a user can see and manipulate some different data. All of these data serves as input and also as output of a calculation. Two of these widgets share the same data/class, but manipulate different members of this class.

How can I achieve that manipulating the data in one widget automaticly updates the other widget?

So the question is: Can I share a QSharedPointer between two classes, then connect it to a "this"-slot so that when I manipulate the pointer's value in one of these classes, the other one can do something with this data(as updating it's gui)?

My intention was, since I had to store the actual data in another QSharedPointer, to make a connect on that shared pointer that tells the other widget.

I thought of something like this:


#include <QWidget>
#include <QSpinBox>

class MyWidget : QWidget // A template widget to be placed in MainWindow
{
    Q_OBJECT
public:
    MyWidget()
    {
        this->spinBox = new QSpinBox(this);
        connect(this->spinBox, &QSpinBox::editingFinished, this, &MyWidget::evokedByGuiManipulation);
        connect(this->data.data(), &foo::changed, this, &MyWidget::updateGui);
    }
    virtual ~MyWidget() {delete spinBox;}

public slots:
    void setData(QSharedPointer<foo> value)
    {
        data = value;
    }

    void evokedByGuiManipulation()
    {
        data->manipulate(spinBox->value());
    }

    void updateGui()
    {
        this->spinBox->setValue(data->getData()->datamember);
    }
protected:
    QSharedPointer<foo> data;

private:
    QSpinBox *spinBox;
};

UPDATE

And class foo is actually a wrapper that stores the actual data class baz. Like:

class foo
{
    Q_GADGET
public:
    foo(){}
    QSharedPointer<baz> getData() {return actualData;}

public slots :
    void setActualData(QSharedPointer<baz> value)
    {
        actualData = value;
        emit changed();
    }

signals:
    void changed();

private:
    QSharedPointer<baz> actualData;
};
void
  • 142
  • 9

1 Answers1

0

You can do this, assuming that foo::manipulate emits a signal that your other widget connects to.

I would also advise ensuring that foo::operator= emit changed, so that setData updates both widgets.

Not strictly related to your question, there are errors in the code you have shown.

connect(this->spinBox, &QSpinBox::editingFinished, this, &MyWidget::evokedByGuiManipulation);

editingFinished doesn't have a QSharedPointer<baz> to pass to evokedByGuiManipulation. Did you mean

data->manipulate(spinBox->value());
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Okay sorry, I didn't clarify my wrapper class `foo` enough. So here I got the problem that, when I do foo::manipulate I always got a new SharedPointer, so I also had to make a new connection. But what I actually wanted is to manipulate the actual data in place – void Apr 21 '20 at 08:22
  • *Why* do you have a new `foo` each time, and not a sharing of the same `foo` multiple times? – Caleth Apr 21 '20 at 08:25
  • Imageine `setData` with new data from the calculation. Now I want to update both the connected widgets at one time instead of setting the new `foo` for both widgets – void Apr 21 '20 at 08:30
  • Then do `*data = *value;`, and have `foo::operator=` emit `changed`. I'd also change it to `setData(const foo & value)` – Caleth Apr 21 '20 at 08:33