how to get selected rows in QTableView - qt

After watching many threads about getting selected rows numbers, I am really confused.
How do you get ROW numbers in QTableView using QStandardItemModel I used below selection model and behavior as
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
and if you have your own way of selecting can you explain how it works.
Thanks for the help!

The method selectionModel() return a QItemSelectionModel.
You can use QItemSelectionModel class to check/change/other selection(s)
Example:
QItemSelectionModel *select = table->selectionModel();
select->hasSelection() //check if has selection
select->selectedRows() // return selected row(s)
select->selectedColumns() // return selected column(s)
...

Check selectedRows method of the QItemSelectionModel Class .
QModelIndexList selection = yourTableView->selectionModel()->selectedRows();
// Multiple rows can be selected
for(int i=0; i< selection.count(); i++)
{
QModelIndex index = selection.at(i);
qDebug() << index.row();
}

try:
QModelIndexList indexList = yourTableView->selectionModel()->selectedIndexes();
int row;
foreach (QModelIndex index, indexList) {
row = index.row();
....
}

Since you use
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
so only one row can be selected each time, then you can try this:
auto rowList = yourTableView->selectionModel()->selectedRows();
if(rowList.count() > 0)
int rowNumber = rowList.constFirst().row();
else
// no row is selected

Related

create a table in Qt and fill it by the user

i want to create an Qt application containing a table of 3 columns and n row, the user will choose the number of row by putting it in the edit button and the table will have 3 columns and the number given by the user. then fill it with element
i have search a lot but only found how to fill the able with sql data,
please is anybody having an idea?
here is what i did so far, i have fixed the number of rows and columns but it is not what i want, besides, i want to use either QtableWidget or QtavleViewItem
int n;
n = ui->spinBox->value();
QStandardItemModel *model = new QStandardItemModel(n,3,this); //2 Rows and 3 Columns
model->setHorizontalHeaderItem(0, new QStandardItem(QString("x")));
model->setHorizontalHeaderItem(1, new QStandardItem(QString("y")));
model->setHorizontalHeaderItem(2, new QStandardItem(QString("z")));
ui->tableView->setModel(model);
you can go through the elements in a QTableView and do things with them:
for(int r=0; r<N_ROWS; r++)
{
for(int c=0; c<N_COLS; c++)
{
QModelIndex index = ui->tableView->model()->index(r,c, QModelIndex());
// Do something with the QVariant that index.data() returns
qDebug() << r << c << index.data().toString();
}
}
Regards.

Doubleclick on QTreeView shall always return first columns value

I have my QTreeView where whole rows were selected:
ui->treeView->setSelectionBehavior (QAbstractItemView::SelectRows);
...and already filled with ID-Number <--> Description. All are structured as a tree. I can click it, and retreive corresponding selection via:
ui->lineEdit->setText( modelIndex.data(Qt::DisplayRole).toString() );
and I already connected:
connect(ui->treeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onSelectedTreeView(QModelIndex)));
When I click on a ID-Number, it works perfectly, and my modelIndex.data() returns the ID-Number.
When I click on the description, my modelIndex.data() returns its correct description (second column). BUT I would like to have again the corresponding ID-Number (first column).
I appreciate any help. Thanks in advance.
You can use the sibling(int row, int column) method of QModelIndex
In python:
def onSelectedTreeView(index):
firstColumnIndex=index.sibling(index.row(),0)
print(firstColumnIndex.data())
I guess you could do:
ui->lineEdit->setText(modelIndex.sibling(modelIndex.row(),0).data(Qt::DisplayRole).toString());
You can change treeView selectionBehavior to SelectItems. Than use index.row() and index.column().. And dont forget that it always start from 0
onSelectedTreeView()
{
//Put all your selected indexes into QModelIndexList
QModelIndexList _indexes = ui->treeView->selectionModel()->selectedIndexes();
// For each loop for every selected index..
foreach (QModelIndex index, _indexes)
{
//if your index data == 0 it means that you clicked into ID-number field.
//So you can easly see which index you clicked with qdebug
qDebug() << "Row = " << index.row() << "\t Column = " << index.column();
// So if you want to get always index of first column(ID-Number) use QAbstractItemModel
if(index.column().toInt() != 0 ) //if your index not equal to 0
{
const QAbstractItemModel* absModel = index.model();
// change index of absModel from index.column() to 0;
QModelIndex changedIndex = absModel->data(absModel->index(index.row(), 0), Qt::DisplayRole).toInt();
qDebug() << "Row = " << changedIndex.row() << "\t Column = " << changedIndex.column();
}
}
}

Qt - how to access QComboBox data inserted in QTreeWidget

During runtime I have inserted QCombobox in my QTreeWidget like this:
//global defines
#define COLUMN_1 (0)
#define COLUMN_2 (1)
//Init QComboBox to QTreeWidget - works fine.
QTreeWidgetItem *item = new QTreeWidgetItem(_myTreeWidget);
item->setText(COLUMN_1,"testing");
QComboBox *box = new QComboBox();
box->addItem("select1");
box->addItem("select2");
box->addItem("select3");
_myTreeWidget->setItemWidget(item, 1, box);
The above code works, but I also want to read the data text in these columns. Eg. get the strings "testing" & "select2" from code above. The problem is that I can't figure out how to read the "QComboBox::currentText()" in the comboboxes.
I have tried:
QTreeWidgetItemIterator it(_myTreeWidget);
while(*it)
{
QTreeWidgetItem *item = *it;
QVariant first = item->text(COLUMN_1);
QString firstStr = loggerName.toString(); //this works
QComboBox *box = (QComboBox*)item->data(COLUMN_2, 0);
QString boxValStr = box->text().toString(); //this doesn't works, always empty string
//... more code to handle strings...
it++;
}
Feels like the "item->data(COLUMN_2, 0)" is wrong way to go cause it returns a QVariant.
Solution on this problem?
QComboBox *box = (QComboBox*)item->data(COLUMN_2, 0);
When I read this code, I went into panic mode. Look at the signature:
QVariant QTreeWidgetItem::data ( int column, int role ) const
As you used setItemWidget, you should probably use
QWidget * QTreeWidget::itemWidget ( QTreeWidgetItem * item, int column ) const
ps: If you want to cast, use C++ casts. Much better, use qobject_cast<SubtypeofQObjectPtr> for QObject. It returns null when the cast is invalid.
Indeed, I mean retrieve the combobox using a call similar to :
QComboBox* box = qobject_cast<QComboBox*>(treeWidget->itemWidget(item, column));
Solved it thanks to the help from #Umnyobe and #Zaiborg above. Here is a total working example:
Init QTreeWidget with text in column1 and QComboBox in column2:
//global defines
#define COLUMN_1 (0)
#define COLUMN_2 (1)
QTreeWidgetItem *item = new QTreeWidgetItem(_myTreeWidgetPtr);//item to put in tree
item->setText(COLUMN_1,"animal"); //item for column 1 in the tree.
QComboBox *box = new QComboBox();
box->addItem("mouse"); //adds selections for comboboxes
box->addItem("cat");
box->addItem("dog");
_myTreeWidgetPtr->setItemWidget(item, COLUMN_2, box); //insert items in tree.
Read values from tree:
QTreeWidgetItemIterator it(_myTreeWidgetPtr);
while(*it)
{
QTreeWidgetItem *item = *it;
//Init pointer to current combobox
QComboBox* box = qobject_cast<QComboBox*>(_myTreeWidgetPtr->itemWidget(item, COLUMN_2));
//Get data from QTreeWidget
QString col1Str = item->text(COLUMN_LOGGER);
QString col2Str = box->currentText();
it++;
}
hope it can help someone :)
use the QSignalMapper class to collect the different boxes in the treewidget.
then connect the QSignalMapper::mapped() signal to some slot and use the combobox
edit:
QSignalMapper* mapper = new QSignalMapper(this);
QComboBox *box = new QComboBox();
connect( box, SLOT(/*whatever*/), mapper, SLOT( map() ) );
mapper->setMapping( box );
myTreeWidget->setItemWidget(item, 1, comboBox);
For anyone who is looking for a Python solution,
(PySide / PyQt QComboBox in QTreeWidget), here is it:
item = QTreeWidgetItem(self.treeWidgetAnimals)
item.setText(0, "animal")
combo_box = QComboBox()
combo_box.addItem('mouse')
combo_box.addItem('cat')
combo_box.addItem('dog')
self.treeWidgetAnimals.setItemWidget(item, 1, combo_box)
I was looking for hours but no other forum like pass reference "parent" like a "delegation":
        item = QTreeWidgetItem (self.myTreeWidgetItemObject)
if you do not pass the parent, error ir not returned but the ComboBox not appears in display TreeWidget.

Deleting multiple rows in QTableView

While searching for clues on how i can delete multiple rows from QTableView i came across this function: remove selected rows from QTableView
Here is the code:-
QItemSelection selection( ui.tableView->selectionModel()->selection() );
QList<int> rows;
foreach( const QModelIndex & index, selection.indexes() ) {
rows.append( index.row() );
}
qSort( rows );
int prev = -1;
for( int i = rows.count() - 1; i >= 0; i -= 1 ) {
int current = rows[i];
if( current != prev ) {
tableModel->removeRows( current, 1 );
prev = current;
}
}
I need help writing the query doing that.I have been trying this:-
query.exec(QString("DELETE FROM %1 id IN %2").arg(tableName,rows));
but i think i should be using QStringList somewhere but i am still reading the QList examples.Anyone?.
Since you seem to be using a QSqlTableModel:
in QSqlTableModel::OnFieldChange or OnRowChange modes, removeRows also deletes the records from the database.
in QSqlTableModel::OnManualSubmit mode you have to call QSqlTableModel::submitAll() at the end of the loop.
If you were using a QSqlQueryModel, you would have to subclass that model to implement the deletion within removeRows.

sort row by column , when getting text always wrong

I'm trying to get text and data from column in index number 0 from row that is selected
but I never get the right data I'm using simple model view TreeView with QSortFilterProxyModel proxy to sort the columns and QStandardItemModel as the model
This is the slot function that is triggered on each doubleClicked
connect(ui.treeView_mainwindow, SIGNAL(doubleClicked( const QModelIndex &)), this,SLOT(tree_itemClicked( const QModelIndex &)));
....
...
void MainWindowContainer::tree_itemClicked(const QModelIndex & index)
{
int iSelectedRow = index.row();
QString groupID;
QString groupName;
groupID = m_model->item(iSelectedRow,0)->data(Qt::UserRole).toString();
groupName = m_model->item(iSelectedRow,0)->text();
}
UPDATE:
Well, I found the answer but I have another question, the answer is :
QString groupID = index.model()->index(index.row(), 0, index.parent()).data(Qt::UserRole).toString();
QString groupName = index.model()->index(index.row(), 0, index.parent()).data(Qt::DataRole).toString();
}
My other question is how do I set data to column in index ( for example: 3 ) in the selected row?
The problem here most likely is that index.row() points to the row in the proxy model after sorting. This is most likely not the same row in your unsorted source model.
Try the following instead:
groupID = m_proxy_model->index(iSelectedRow,0).data(Qt::UserRole).toString();
Have you tried using
QStandardItem * QStandardItemModel::itemFromIndex ( const QModelIndex & index ) const;
Perhaps your rows are not set properly.
If this does not help, you should give an example tree, indicate what you click, what you expect, what you get.
QModelIndex modelIndex = m_proxy_model->index(iSelectedRow,0);
m_proxy_model->data (modelIndex ,Qt::UserRole).toString();

Resources