flog
flog

Reputation: 13

Qt signals and slots passing data

I'm pretty new to c++ and qt. I'm not sure if i use the right terminology describe what I want to achieve. But here it goes.

My application spawns and removes widgets in a gridlayout when the user pushes buttons. Managed to do this successfully. However when the user uses the spawned widgets I want the widgets to interact with each other.

QList<QLineEdit*> m_ptrLEPathList;
QList<QPushButton*> m_ptrPBList;

qint8 m_noFields;

void MainWindow::on_pbIncFields_clicked()
{
    //create widgets and place on a new row in a gridLayout
    QLineEdit *lineEditPath = new QLineEdit(this);
    QPushButton *pushButton = new QPushButton(this);

    //storing pointers in lists to be able to delete them later.
    m_ptrLEPathList.append(lineEditPath);
    m_ptrPBList.append(pushButton);

    ui->gridLayout->addWidget(m_ptrLEPathList.last(),m_noFields,0);
    ui->gridLayout->addWidget(m_ptrPBList.last(),m_noFields,1);

    connect(m_ptrPBList.last(), SIGNAL(clicked(bool), this, SLOT(on_addPath()));
    m_noFields++;
}

void MainWindow::on_pbDecFields()
{
    //delete last spawned widgets
}

void MainWindow::on_addPath()
{
    QFileDialog getPath();
    getPath.exec();

    //somehow set the text of the line edit spawned on the same row as the pushbutton

}

So my slot is executed when I push any spawned button but I have no idea how to store the data from the file dialog in the related lineEdit.

Is the basic idea of what I'm trying to do ok or is there any other solution to achieve the fuctionality I'm looking for?

Upvotes: 1

Views: 1892

Answers (5)

thuga
thuga

Reputation: 12901

I think the cleanest solution would be to contain the QLineEdit and QPushButton in a custom widget class, if it suits your project. That way you could use the file dialog inside this class, and you won't have to store the widgets in lists. It is hard to give you all the information, as you didn't really provide any details what your application is supposed to do. But in any case, the custom widget class would look something like this (you should define all the functions inside a .cpp file):

#ifndef WIDGETCONTAINER_H
#define WIDGETCONTAINER_H

#include <QWidget>
#include <QLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QFileDialog>

class WidgetContainer : public QWidget
{
    Q_OBJECT
    public:
    WidgetContainer(QWidget *parent = 0) : QWidget(parent)
   {
       setLayout(new QHBoxLayout);
       button.setText("BUTTON");
       layout()->addWidget(&lineEdit);
       layout()->addWidget(&button);

       connect(&button, SIGNAL(clicked()), this, SLOT(buttonPressed()));
   }

private:
    QLineEdit lineEdit;
    QPushButton button;

private slots:
    void buttonPressed()
    {
        QString filename = QFileDialog::getSaveFileName();
        lineEdit.setText(filename);
    }    

};

#endif // WIDGETCONTAINER_H

Upvotes: 0

Alexander Chernin
Alexander Chernin

Reputation: 444

Add a map to private section

QMap<QPushButton*, QLineEdit*> map;

Then

QLineEdit *lineEditPath = new QLineEdit(this);
QPushButton *pushButton = new QPushButton(this);
map.insert(pushButton, lineEditPath);

You can use sender() method like follow:

    void on_addPath()
    {
        QFileDialog getPath();
        getPath.exec();

        QObject* obj = sender();
        QPushButton *pb = 0;
        if((pb = qobject_cast<QPushButton *>(obj)) != 0) {
            QLineEdit* lineEdit = map->value(pb, 0);
            if( lineEdit != 0 )
                lineEdit->setText( getPath.<some function to get selected file name> );
        }         

    }

Upvotes: 0

Marcus
Marcus

Reputation: 1703

First off, void on_addPath() must be void MainWindow::on_addPath()

As for linking the data from QFileDialog it is simple. Try this:

void MainWindow::on_addPath() {
    /* Get the push button you clicked */
    QPushButon *btn = qobject_cast<QPushButton*>( sender() );

    /* Make sure both the lists have the same size */
    Q_ASSERT(m_ptrPBList.size() == m_ptrLEPathList.size());

    /* If the sender is a button in your list */
    if ( m_ptrPBList.contains( btn ) ) {
        /* Get the index of your push button */
        int idx = m_ptrPBList.indexOf( btn );

        /* Get the corresponding line edit */
        QLineEdit *le = m_ptrLEPathList.at( idx );

        /* Get your path */
        QString path = QFileDialog::getOpenFileName( this, "Caption", "Default Location" );

        /* If you path is not empty, store it */
        if ( not path.isEmpty() )
            le->setText( path );
    }
}

Upvotes: 0

goe
goe

Reputation: 2303

You are including 'on_addPath' function out of the scope of the 'MainWindow' class, so when the slot is called you have not access to member elements in the class.

Try to include the slot function into the class and check if you have direct access to the member elements. Also, the 'lineEditPath' element must be a member object, so it must be included into the class definition.

Something like this:

void MainWindow::on_addPath()
{
    QFileDialog getPath();
    getPath.exec();

    QStringList fileNames = dialog.selectedFiles();
    if (fileNames.isEmpty())
    {
        return;
    }

    m_lineEditPath->setText(fileNames.first());
}

Upvotes: 0

hank
hank

Reputation: 9853

In on_addPath slot you can use QObject::sender method to get the clicked button, and, assuming m_ptrLEPathList and m_ptrPBList lists are equal, you can easily get the corresponding QLineEdit:

void MainWindow::on_addPath()
{
    QFileDialog dialog;
    if (!dialog.exec())
    {
        return;
    }

    QStringList fileNames = dialog.selectedFiles();
    if (fileNames.isEmpty())
    {
        return;
    }

    QPushButton *btn = qobject_cast<QPushButton*>(sender());
    if (!btn)
    {
        return;
    }

    Q_ASSERT(m_ptrPBList.size() == m_ptrLEPathList.size());

    int index = m_ptrPBList.indexOf(btn);
    if (index == -1)
    {
        return;
    }

    QLineEdit *edit = m_ptrLEPathList.at(index);
    edit->setText(fileNames.first());
}

Upvotes: 2

Related Questions