Mr Squid
Mr Squid

Reputation: 1276

Connecting two signals with different arguments

I want to get a QTreeView widget to emit a clicked(const QModelIndex&) signal whenever a pushbutton is clicked. This is so that I can get a list of all the items that are selected within the QTreeView at the time of clicking the pushbutton. Now I thought I could connect two signals with distinct arguments (Qt Connect signals with different arguments), however when I try to call

connect(ui.pbAddVideo, SIGNAL(clicked()), ui.treeView_video, SIGNAL(clicked(const QModelIndex&)));

I get the error message:

QObject::connect: Incompatible sender/receiver arguments QPushButton::clicked() --> QTreeView::clicked(QModelIndex)

Have I misunderstood the whole signal forwarding concept?

As always, many thanks.

Upvotes: 0

Views: 441

Answers (5)

Mr Squid
Mr Squid

Reputation: 1276

Many thanks to @vahancho whose answer I have adopted. There is no point in using the "clicked()" signal from the qTreeView since I do not need to wait for this to access the data inside. Hence:

connect(ui.pbAddVideo, SIGNAL(clicked()), this, SLOT(addVideo()));

    void VigilWidget::addVideo() {

    QItemSelectionModel *selectionModel = ui.treeView_video->selectionModel();
    QModelIndexList selectedVideos = selectionModel->selectedIndexes();
    foreach (QModelIndex video, selectedVideos) {
        qDebug().nospace() << video.data(0);
    }

}

As to my question about how signal to signal connections work, thanks to everyone for taking the time to explain this :)

Upvotes: 0

JKSH
JKSH

Reputation: 2718

Have I misunderstood the whole signal forwarding concept?

Yes.

When a signal is emitted, Qt takes the signal's arguments and passes them to the connected slot/signal.

Valid signal-slot connection

For example, suppose you connect the QSlider::valueChanged(int) signal to the QSpinBox::setValue(int) slot. When the valueChanged() signal is emitted, this is effectively how the slot gets called:

// "Emitting a signal" == "Calling the signal function"
QSlider::valueChanged(int sliderSignalValue)
{
    QSpinBox *receiver = findReceiver();
    receiver->setValue(sliderSignalValue);
}

Valid signal-signal connections

Similarly, if you connect the QSlider::valueChanged(int) signal to the QSpinBox::valueChanged(int) signal, the code behaves like this:

QSlider::valueChanged(int sliderSignalValue)
{
    QSpinBox *receiver = findReceiver();
    emit receiver->valueChanged(sliderSignalValue);
}

Now, if you want to connect in the opposite direction (connect(ui.treeView_video, SIGNAL(clicked(const QModelIndex&)), ui.pbAddVideo, SIGNAL(clicked()));, it's perfectly fine:

QTreeView::clicked(const QModelIndex& viewSignalValue)
{
    QPushButton *receiver = findReceiver();
    emit receiver->clicked(); // No problem. The viewSignalValue is simply ignored.
}

Invalid signal-slot connection

However, for the connection that you wanted to make, the code will need to behave like this:

QPushButton::clicked()
{
    QTreeView *receiver = findReceiver();
    emit receiver->clicked(/*???*/); // ERROR: You need to pass a QModelIndex value!
} 

You've got a parameter mismatch. QTreeView::clicked() requires a QModelIndex value, but QPushButton::clicked() cannot provide this. Therefore, you cannot connect these two together.

Does this make sense?

Upvotes: 0

vahancho
vahancho

Reputation: 21220

I would solve your problem with the following approach:

First you have to handle the button click:

connect(ui.pbAddVideo, SIGNAL(clicked()), this, SLOT(onLoadVideo()));

In the slot you need to get the list of selected items from the tree view and do something with them:

void MyClass::onLoadVideo()
{
    QItemSelectionModel *selectionModel = ui.treeView_video->selectionModel();
    QModelIndexList selectedVideos = selectionModel->selectedIndexes();
    foreach (QModelIndex *video, selectedVideos) {
        // Play the video.
    }

}

Upvotes: 1

Yousuf Azad
Yousuf Azad

Reputation: 415

You are connecting one SIGNAL() to another SIGNAL() which is perfectly ok but their parameters should match. In your case the second signal has a parameter(i.e QModelIndex) that the first signal does not have.

Upvotes: 0

Shtol Krakov
Shtol Krakov

Reputation: 1280

Firtsly, what index you must send by clicking a button from your tree? Secondly, since c++11 standart you can do something like that:

connect(ui.pbAddVideo, &QPushButton::clicked, [=] { emit ui.treeView_video->clicked(ui.treeView_video->currentIndex()); });

Upvotes: 3

Related Questions