PDA

View Full Version : Detecting row selection in a QTableView



scarleton
7th June 2010, 16:23
How does a QTableView signal/notify that the whole row has been selected and unselected? Not just a cell, but when the user clicks on the 'virtual row header' which is to the left of the first cell in the row.

The goal is this: when a user selects a whole row, enable a button on the form which will allow the user to act upon the selected row. It is also important to know when no row is selected, so the button is not enabled.

Might there be some way to wire this up between the QTableView's model and the button?

Sam

waynew
8th June 2010, 02:03
This works for me


connect(view, SIGNAL(clicked(const QModelIndex&)), this, SLOT(recordSelected()));

//then
void MainWindow::recordSelected()
{
QModelIndex index = view->currentIndex();
QSqlRecord record;
int i = index.row(); // now you know which record was selected
record = model->record(i);
// and I do something with the record
}


So what do you need the button for then?

saa7_go
8th June 2010, 03:29
maybe, subclassing QTableView can achieve what you want.

tableview.h :



#ifndef TABLEVIEW_H
#define TABLEVIEW_H

#include <QTableView>

class TableView : public QTableView
{
Q_OBJECT
public:
TableView(QWidget *parent = 0);

protected:
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);

signals:
void rowSelected(int row_num);
void rowSelected(bool val);
};

#endif // TABLEVIEW_H


tableview.cpp :



#include "tableview.h"
#include <QItemSelection>
#include <QHeaderView>

TableView::TableView(QWidget *parent) : QTableView(parent)
{
}

void TableView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
QTableView::selectionChanged(selected, deselected);

if(model() != 0)
{
if(selectedIndexes().count() == 0)
{
emit rowSelected(false);
return;
}

int count = 0;
int row = selectedIndexes().at(0).row();

foreach(QModelIndex m, selectedIndexes()) {
if(m.row() == row)
count++;
else
return;
}

if(count == horizontalHeader()->count())
{
emit rowSelected(true);
emit rowSelected(row);
}
else
{
emit rowSelected(false);
}
}
}


main.cpp :



#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QFileSystemModel>
#include "tableview.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QWidget w;
QVBoxLayout *lay = new QVBoxLayout(&w);
QPushButton *button = new QPushButton("Go");
button->setEnabled(false);

TableView *v = new TableView;
QFileSystemModel model;
model.setRootPath("C:/");
v->setModel(&model);

lay->addWidget(v);
lay->addWidget(button);

QObject::connect(v, SIGNAL(rowSelected(bool)), button, SLOT(setEnabled(bool)));
w.show();

return app.exec();
}

scarleton
8th June 2010, 03:35
Well, that works for me as long as I click in a cell.

I am calling the little box to the LEFT of the first cell, where the table displays the row number, the "row header". When I click on this "row header", the slot is never called. I played around a bit more and discovered that selectionBehavior was set to QAbstractItemView::SelectRows. When I changed it to QAbstractItemView::SelectItems, then it was not possible to select the "row header".

I want to differentiate between clicking on a cell in a row and selecting the whole row. Is that possible?

Sam

norobro
8th June 2010, 04:01
Take a look at the signals emitted by QHeaderView.
For instance, you could connect QTableView::verticalHeader()->sectionPressed() to a slot that enables your button.

saa7_go
8th June 2010, 04:01
how about connecting the vertical header view to your slot?

for example:



connect(tableView->verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(yourCustomSlot(int)));

scarleton
8th June 2010, 04:09
Thank you, that was it, getting the signal off the header.