I have a QTableWidget, which displays files.
What I want to do is be able to select 1 or multiple rows from this table and pass the first column contents of each row into a function to be able to manipulate.
QModelIndexList indexList = ui->filesTable->selectionModel()->selectedIndexes();
int row;
foreach (QModelIndex index, indexList) {
row = index.row();
qDebug() << row;
}
I've got this code but this passes the indexes in and I need the contents of the first column of the QTableWidget on the row or rows I select.
Thanks for any help in advance!
To get the content of a cell you need to use QModelIndex::data method:
QModelIndexList indexList = ui->filesTable->selectionModel()->selectedIndexes( );
foreach (QModelIndex index, indexList)
{
qDebug() << index->data( Qt::DisplayRole );
}
You can retrieve more information about selected cells just changing the role. Custom models can accept custom roles.
Related
I am working with a qtableview that is filled by a model and has two columns. I can get the contents of a selected cell no problem but only want the contents of the second column even if the first column is clicked.
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
QString cellText;
if (index.isValid()) {
cellText = index.data().toString();
}
ui->lineEdit->setText(cellText);
}
the index looks like this for column 0:
QModelIndex(7,0,0x55f2e5d06b00,QStandardItemModel(0x55f2e5d09740))
And for column 1:
QModelIndex(8,1,0x55f2e5d06b00,QStandardItemModel(0x55f2e5d09740))
I tried to find a way to change the index for the cell that is clicked but I think there is no way to change it directly and I can not seem to find a way to tell my function to always use column 1 the second column.
Thanks for your time.
Code edited to reflect comment 1 below
{
QString cellText;
if (index.isValid()) {
QModelIndex idx = index;
idx = idx.sibling(idx.row(), 1);
cellText = idx.data().toString();
}
ui->lineEdit->setText(cellText);
}```
I'm trying to put a MySQL table into a treeView.
Each entry has three values in the database - id, text, parentId.
This treeView needs to be editable so I really like the QSqlTableModel approach, as the functionality to save back to database is already built in.
Now, the treeView is showing all entries in the same line, of course, and I need a hierarchy. What would be the best way to build this hierarchy, while maintaining the editing and saving capabilities?
(I'm using MySQL.)
mainwindow.h
private: QSqlTableModel* goalModel;
mainwindow.cpp
(this makes a flat table hierarchy. the table is filtered based on which entry is clicked in another table)
void MainWindow::on_tableViewGoals_clicked(const QModelIndex &index)
{
goalModel = new QSqlTableModel(this);
goalModel->setTable("goals");
//Gets the id from the clicked entry to use as filter
QString idGoals = index.sibling(row,0).data().toString();
goalModel->setFilter( "id_goals=" + idGoals );
goalModel->setEditStrategy(QSqlTableModel::OnRowChange);
goalModel->select();
ui->treeView->setModel(goalModel);
...
I tried this. It's wrong, but I don't really know why. (the third column contains the parentId value, if the entry has it)
for (int row = 0; row < goalModel->rowCount(); ++row)
{
//if the entry has a value over 0 in the parentId column
if (goalModel->index(row,2).data().toInt() > 0)
{
//get number in column 2
int parentId;
parentId = goalModel->index(row,2).data().toInt();
QModelIndex newChild = goalModel->index(row,0);
//find QModelIndex row with matching number in column 0
for (int row = 0; row < goalModel->rowCount(); ++row)
{
if (goalModel->index(row,0).data().toInt() == parentId )
{
//make this entry that entry's child
QModelIndex newParent = goalModel->index(row,0);
newChild = goalModel->index(0,0,newParent);
}
}
}
}
All indexes are already made, so no need to make new ones, just assign a parent to all those who have one. How best to do that?
I want to assign the particular material Id to the combo box once I click on a row in Table view.
void FictionSection::on_tblFiction_clicked(const QModelIndex &index)
{
int indicator = ui->tblFiction->model()->data(index).toInt();
QSqlQuery query;
query.prepare(" select fic_bk_id,material_id,no_of_cpy,shelf_num,edition from fiction "
"where material_id= :id or no_of_cpy=:copy or shelf_num=:shelf or edition=:edition");
query.bindValue(":id",indicator);
query.bindValue(":copy",indicator);
query.bindValue(":shelf",indicator);
query.bindValue(":edition",indicator);
//Assigning table values to fields
if(query.exec())
{
while(query.next())
{
ui->lneditMngFicId->setText(query.value(0).toString());
ui->cmboxMngId->setCurrentText(query.value(1).toString());
ui->lneditMngCpy->setText(query.value(2).toString());
ui->spinbxMngShlf->setValue(query.value(3).toInt());
ui->spinbxMngEdtn->setValue(query.value(4).toInt());
}
}
else
{
QMessageBox :: critical(this,"Error","Couldn't load the values");
}
}
Although other fields get the values once I click on any row combo box do not get the required value. material_id is stored as an int in database. I tried a lot to solve this.Please help me to solve this. Thank you in advance
Is it because of the space in your query related to material_id:
material_id= :id
I have a table where user can select multiple rows, however I need to know indexes of top and last selected row, I tried playing with http://qt-project.org/doc/qt-5/QModelIndex.html so far I have this:
QItemSelectionModel *selections = this->ui->tableWidget->selectionModel();
QModelIndexList selected = selections->selectedRows(3);
But I have no idea how can I use QItemSelectionModel to reach the item of table. How can I do that? There is no function in TableWidget that returns item based on QModelIndex, only QPoint
In order to get the first and last item in the selection range you can simply sort that list. For example:
QItemSelectionModel *selections = this->ui->tableWidget->selectionModel();
QModelIndexList selected = selections->selectedRows(3);
qSort(selected);
QModelIndex first = selected.first();
QModelIndex last = selected.last();
And now let's get the first and last table items:
QTableWidgetItem *firstItem = this->ui->tableWidget->item(first.row(), first.column());
QTableWidgetItem *lastItem = this->ui->tableWidget->item(last.row(), last.column());
Is QTableWidget::item(int row, int column) together with QModelIndex::column () and QModelIndex::row (), respectively, of any help?
How can I implement this code I have for a qTreeWidget for a qTreeView?
for (const auto & i : names) {
QTreeWidgetItem * item = new QTreeWidgetItem(ui->treeWidget);
item->setText(0, QString::fromStdString(i));
ui->treeWidget->addTopLevelItem(item);
const std::unordered_map<std::string, double> map = m_reader.getMapFromEntry(i);
for (const auto & j : map) {
QTreeWidgetItem * item2 = new QTreeWidgetItem();
item2->setText(0,QString::fromStdString(j.first));
item2->setText(1,QString::number(j.second));
item->addChild(item2);
}
}
I have a model and a treeView, like this:
m_model = new QStandardItemModel(m_reader.getAllNames().size(),2,this);
ui->treeView->setModel(m_model);
I tried this, but that only shows one column:
QStandardItem * parentItem = m_model->invisibleRootItem();
for (const auto & i : names) {
QStandardItem * item = new QStandardItem(QString::fromStdString(i));
parentItem->appendRow(item);
const std::unordered_map<std::string, double> map = m_reader.getMapFromEntry(i);
for (const auto & j : map) {
QList<QStandardItem *> rowItems;
rowItems << new QStandardItem(QString::fromStdString(j.first));
rowItems << new QStandardItem(QString::number(j.second));
item->appendRow(rowItems);
}
}
With the treeWidget, I had so set the columnCount, like this:
ui->treeWidget->setColumnCount(2);
But treeView does not have a method like this.
So, to summarize: How can I implement a TreeView with more than one column?
EDIT:
To clarify, I want something like this:
|-A
| |-B-C
| |-D-E
where A is the parent and B,C,D,E the children, with B,D being in column 0 and C,E in column 1.
Hope this helps!
To support multiple columns, the model must contain data for multiple columns.
So in some sense, columns are a property of the model, not the view. Views then can decide to hide or rearrange certain columns (For example, a QListView always only shows the first column, while one can hide or reorder columns in a QTableView).
As you use QStandardItemModel, its documentation should give a few hints how to create multiple columns.
E.g., look at this example from the documentation:
QStandardItemModel model(4, 4);
for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 4; ++column) {
QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
model.setItem(row, column, item);
}
}
It creates a model with 4 initial rows and columns each, and then fills it with items via setItem().
Alternatively, you can pass a list of items to QStandardItemModel::appendRow(), with an item for each column:
QList<QStandardItem*> items;
items.append(new QStandardItem(tr("One"));
items.append(new QStandardItem(tr("Two"));
model->appendRow(items);
This adds a new row with "One' in the first column and "Two" in the second. For even more ways to deal with multiple columns, see the QStandardItemModel docs.
Note: QTreeView expects the same number of columns on all levels of the hierarchy, so one should fill rows with empty items for the unused columns if need be.
Just an addition to answer by Frank Osterfeld:
QTreeView displays all columns of subtables inserted into top level QStandardItems. You just have to "force" it to show additional columns by inserting dummy QStandardItems into top-level table. Example:
QStandardItemModel *objectTreeModel = new QStandardItemModel(NULL);
QStandardItem *mainItem = new QStandardItem(tr("Main Item"));
QStandardItem *subItem1 = new QStandardItem(tr("Sub-Item 1"));
QStandardItem *subItem2 = new QStandardItem(tr("Sub-Item 2"));
mainItem->appendRow(QList<QStandardItem *>() << subItem1 << subItem2);
QStandardItem *dummyItem = new QStandardItem();
objectTreeModel->appendRow(QList<QStandardItem *>() << mainItem << dummyItem );
Now you will be able to see 2 columns and if you expand mainItem, both subitems will be visible.