How to get row number for a string in qtablewidget - c++

I am using Qt 5.4.0 and created a QTableWidget. The table has several rows and columns.
In my application I want to search a string in that table and if that string exists, I want to know the row number.
I could not find any such api in qt 5.4.0 documentation.
Does anyone has understanding of such api or similar to what I am looking for.
Thanks in advance !

You can use the match() method of the model:
for (int col=0; col<tableWidget->columnCount(); col++){
// return a list of all matching results
QModelIndexList results = tableWidget->model()->match(
tableWidget->model()->index(0, col),
Qt::DisplayRole,
"yourstring",
-1,
Qt::MatchContains
);
// for each result, print the line number
for (QModelIndex idx : results)
qDebug() << idx.row();
}

You can use findItems method:
QString searchtext = "text";
QList<QTableWidgetItem *> items = ui->tableWidget->findItems(searchtext, Qt::MatchExactly);
for(int i=0; i<items.count(); i++)
{
int row = items.at(i)->row();
//...
}
Notice that you can pass an extra argument to findItems, to set one or more match flags.

Related

How to set a new item in tabview Qt, and save the previous ones

When I use Qt tableView, I can just set item in the first row. When I click add, it will cover the former, but not set a new item. Maybe my slot function is incorrect. But I don't know how to handle it.
void Widget::on_addButton_clicked()
{ int i = 0;
EditDialog editDialog(this);
if(editDialog.exec() == 1)
{
model->setItem(i,0,new QStandardItem(editDialog.getID()));
model->setItem(i,1,new QStandardItem(editDialog.getPriority()));
model->setItem(i,2,new QStandardItem(editDialog.getTime()));
}
i++;
}
Please, have a look into doc. QStandardItemModel::setItem():
Sets the item for the given row and column to item. The model takes ownership of the item. If necessary, the row count and column count are increased to fit the item. The previous item at the given location (if there was one) is deleted.
(Emphasizing is mine.)
If a row shall be inserted before end of table (e.g. as first), then it's necessary to do this explicitly.
This can be achieved by calling QStandardItemModel::insertRow() before setting the items.
This could e.g. look like this:
// fills a table model with sample data
void populate(QStandardItemModel &tblModel, bool prepend)
{
int row = tblModel.rowCount();
if (prepend) tblModel.insertRow(0);
for (int col = 0; col < NCols; ++col) {
QStandardItem *pItem = new QStandardItem(QString("row %0, col %1").arg(row).arg(col));
tblModel.setItem(prepend ? 0 : row, col, pItem);
}
}
I took this from an older post of mine. The complete sample can be found in my answer to SO: Stop QTableView from scrolling as data is added above current position.

I'm using qt to design a program and need help because my code is not DRY [duplicate]

I have a gui form, where multiple text boxes are present. I want to put their values inside an array. One way of doing it is by writing something like this
{array element } = ui->text_1->text();
and repeat it for text_2,text_3 upto n.
What I want is to run a loop and replace number portion of text box name in each cycle.
something like this {array element } = ui->text_{This number getting changed }->text();
How can it be done in qt?
There are two ways of doing this.
When you create the UI, instead of using text1, text2, etc. you create an array of QLineEdits (eg. std::vector<QLineEdit>) and then when you want to retrieve their values then simply iterate over this array
Iterate over the children of the container widget. You can get the list of the children using the following (documentation):
QList<QObject *> list = parentWidget->children();
Another option to those listed would be to create an array using an initializer list. Depending on how big the array is (and how often it changes), this might be workable.
QLineEdit* entries[] = { ui->text_0, ui->text_1, ui=>text_2 };
QStringList answers;
for ( int i = 0; i < 3; ++i )
{
answers += entries[i]->text();
}
here is an expanded version of Matyas' solution:
class MyClass : public QWidget
{
QStringList answers;
void FillAnswersList(QObject *base)
{
QLineEdit *lineEdit = qobject_cast<QLineEdit>(base);
if(lineEdit)answers.append(lineEdit->text());
else
{
foreach(QObject *child, base->children())
FillAnswersList(child);
}
}
};
If it is just the number changing, and always incrementing, there is another possible solution using QObject::findChild, which takes a name as a parameter.
QString name_template("text_%1");
QStringList answers;
for(int i = 0; i < MAX_TEXTS; ++i)
{
QLineEdit *edit = ui->findChild<QLineEdit *>(name_template.arg(i));
answers += edit->text();
}

Get Index of Item Text in MFC CListCtrl

I've got a CString with a Text that also is an Item Text of my CListCtrl. For example:
CString m_SearchThisItemText = _T("Banana");
And in my CListCtrl
m_List.SetItemText (1, 1, _T ("Banana"));
Now I want to find out, on which Index the Text is.
CListCtrl::FindItem
doesnt work. It only searches the name of the Item, not the Text.
I also tried this
for (Index= 0; dlg.GetSearchContentText () == m_List.GetItemText (Index, Spalte); Index++)// HIER IST NOCH EIN FEHLER.
{
if (dlg.GetSearchContentText () == m_List.GetItemText(Index, Spalte))
{
m_List.SetItemState (Zeile, LVIS_SELECTED, LVIS_SELECTED);
m_List.SetFocus();
}
}
But it doesnt work. It stops at Index 0
Can anyone help me, how to find out on which Item the text is.
I hope you understand my question.
Iterate all the items and search in the column you want:
int nCol = 1; // to search in the second column (like your question)
CString m_SearchThisItemText = _T("Banana");
for (int i = 0; i < m_List.GetItemCount(); ++i)
{
CString szText = m_List.GetItemText(i, nCol);
if (szText == m_SearchThisItemText)
{
// found it - do something
break;
}
}
If you mean that you have a list view with several columns and you want to search in other columns than the first one, then FindItem won't help you. You'll have to explicitly write the find code yourself. You must iterate over all the rows in the list, and for each column of a row call GetItemText and compare what you get with the text you have.

Qt C++ Data from a selected row

My row has 5 columns and I need the data from the last column. I've written the below function. This function should return the element from the last column of the selected row, but unfortunately, after debug I've noticed that my function only reads the first column. Can anyone help me to solve this?
QString MainWindow::getIDNumberFromSelectedRow(const QModelIndexList indexes)
{
QStringList selected_text;
foreach(QModelIndex current,indexes)
{
QVariant data = model->data(current);
QString text = data.toString();
selected_text.append(text);
qDebug() << text;
}
QString idNumber = selected_text.last();
return idNumber;
}
Possibly, indexes, and thus, current(s) refers to the first column of the model.
What if you refer directly to a specific item, e.g:
model->data(model->index(current.row(), 4))
I don't know if this work, anyway I hope it'll help

How to delete all rows from QTableWidget

I am trying to delete all rows from a QTableWidget . Here is what I tried.
for ( int i = 0; i < mTestTable->rowCount(); ++i )
{
mTestTable->removeRow(i);
}
I had two rows in my table. But this just deleted a single row. A reason could be that I did not create the the table with a fixed table size. The Qt Documentation for rowCount() says,
This property holds the number of rows in the table.
By default, for a table constructed without row and column counts,
this property contains a value of 0.
So if that is the case, what is the best way to remove all rows from table?
Just set the row count to 0 with:
mTestTable->setRowCount(0);
it will delete the QTableWidgetItems automatically, by calling removeRows as you can see in QTableWidget internal model code:
void QTableModel::setRowCount(int rows)
{
int rc = verticalHeaderItems.count();
if (rows < 0 || rc == rows)
return;
if (rc < rows)
insertRows(qMax(rc, 0), rows - rc);
else
removeRows(qMax(rows, 0), rc - rows);
}
I don't know QTableWidget but your code seems to have a logic flaw. You are forgetting that as you go round the loop you are decreasing the value of mTestTable->rowCount(). After you have removed one row, i will be one and mTestTable->rowCount() will also be one, so your loop stops.
I would do it like this
while (mTestTable->rowCount() > 0)
{
mTestTable->removeRow(0);
}
AFAIK setRowCount(0) removes nothing. Objects are still there, but no more visible.
yourtable->model()->removeRows(0, yourtable->rowCount());
QTableWidget test;
test.clear();
test.setRowCount( 0);
The simple way to delete rows is to set the row count to zero. This uses removeRows() internally.
table->setRowCount(0);
You could also clear the content and then remove all rows.
table->clearContents();
table->model()->removeRows(0, table->rowCount());
Both snippets leave the headers untouched!
If you need to get rid of headers, too, you could switch from clearContents() to clear().
In order to prevent an app crash, disconnect all signals from the QTableView.
// Deselects all selected items
ui->tableWidget->clearSelection();
// Disconnect all signals from table widget ! important !
ui->tableWidget->disconnect();
// Remove all items
ui->tableWidget->clearContents();
// Set row count to 0 (remove rows)
ui->tableWidget->setRowCount(0);
Look this post : http://forum.qt.io/topic/1715/qtablewidget-how-to-delete-a-row
QList<QTableWidgetItem*> items = table.findItems(.....);
QMap<int, int> rowsMap;
for(int i = 0; i < items.count(); i++{
rowsMap[items.at(i).row()] = -1; //garbage value
}
QList<int> rowsList = rowsMap.uniqueKeys();
qSort(rowsList);
//Now go through your table and delete rows in descending order as content would shift up and hence cannot do it in ascending order with ease.
for(int i = rowList.count() - 1; i >= 0; i--){
table.removeRow(rowList.at(i));
}
You can just add empty item model (QStandardItemModel) to your QTableView (myTableView):
itemModel = new QStandardItemModel;
ui->myTableView->setModel(itemModel);
In python you can just set the rowCount to zero and that'll work!
tableWidget.setRowCount(0)
This code is tested with PySide6. Hope it will work for PyQt5 and PyQt6 too.
Your code does not delete last row.
Try this one.
int totalRow = mTestTable->rowCount();
for ( int i = 0; i < totalRow ; ++i )
{
mTestTable->removeRow(i);
}
In your code, on the first time, rowCount() have value 2 and value of the i is 0, so its delete 1st row,
But on the second time value of i incremented with 1, but rowCount() return the updated row count which is now 1, so, it does not delete the last row.
Hope now you ll be clear.
Removes all items not in the headers from the view. This will also remove all selections. The table dimensions stay the same.
void QTableWidget::clearContents()
Removes all items in the view. This will also remove all selections and headers.
void QTableWidget::clear()
This works for me:
for i in reversed(range(self.tableWidget.rowCount())):
self.tableWidget.removeRow(i)