Search code examples
c++qtqtableviewqpushbuttonrow-removal

QTableView row remove


I created a table view like this:

enter image description here

I have a create button to create new rows and as you can see I defined a button for each row to delete that row by this code:

int i = 0;
QPushButton *viewButton;
QStandardItemModel *model;
void MainWindow::on_pushButton_clicked()
{
    model->appendRow(new QStandardItem(QString("")));
    viewButton = new QPushButton();
    viewButton->setText("Delete " + QString::number(i));
    ui->tableView->setIndexWidget(model->index(i , 7), viewButton);
    connect(viewButton , SIGNAL(clicked()) , this , SLOT(button_clicked()));
    i++;
}

and I created a slot for each button clicked for remove a row:

void MainWindow::button_clicked()
{
//   by this line I can get the sender of signal
    QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
}

as you can see I know witch button sends signal and now I need to delete that row. here is my question: how can I get the row of sender button in table view to remove that row? I searched everywhere and I didn’t realise how to get the row and column of an item.


Solution

  • On workaround is to use QObject::setObjectName and set some names to the buttons you add :

    viewButton.setObjectName(QString("%1").arg(i));
    

    And in button_clicked slot you can retrieve the row number using the object name :

    void MainWindow::button_clicked()
    {
    //   by this line I can get the sender of signal
        QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
    
        int row = pb->objectName().toInt();
    }
    

    Note that you should update object names after a row is removed.

    Another way is to use the QSignalMapper class which collects a set of parameterless signals, and re-emits them with integer, string or widget parameters corresponding to the object that sent the signal. So you can have one like:

    QSignalMapper * mapper = new QSignalMapper(this);
    QObject::connect(mapper,SIGNAL(mapped(int)),this,SLOT(button_clicked(int)));
    

    When adding your buttons in each row of table view, you can connect the clicked() signal of the button to the map() slot of QSignalMapper and add a mapping using setMapping so that when clicked() is signaled from a button, the signal mapped(int) is emitted:

    viewButton = new QPushButton();
    viewButton->setText("Delete " + QString::number(i));
    ui->tableView->setIndexWidget(model->index(i , 7), viewButton);
    
    QObject::connect(viewButton, SIGNAL(clicked()),mapper,SLOT(map()));
    mapper->setMapping(but, i);
    

    This way whenever you click a button in a row, the mapped(int) signal of the mapper is emitted containing the row number and consequently button_clicked is called with a parameter containing the row number.

    Also here you should update the mappings in button_clicked slot since the row is removed when you click an item.