Get the actual row number of QTableView after drag and drop - c++

At first, the data of the tableview are
apple
pie
banana
After drag and drop(only drag and drop on itself) the item on the tableview, the data of the tableview looks like following
banana
pie
apple
but when I want to iterate the item of the model one by one
codes
for(int i = 0; i != rowCount(); ++i){
if(item(row, Fruit)){
return item(row, Fruit)->data(Qt::DisplayRole).value<QString>();
}
}
it print the data as
apple
pie
banana
expected result
banana
pie
apple
How could I get the “actual” number after drag and drop?
The easiest solution I can think of is create one more column to store the row number of the model, then override the dropEvent, update the row number when the user drop their row.Any easier way to do it?
Edit :
As the example show, the result I want with the codes is "pie, apple, banana".But the actual result is "banana, pie, apple"

The model always operates on the logicalIndex. You need to use the visualIndex of the verticalHeader() for iterating.
for(int i = 0; i < rowCount(); ++i)
{
// i is the logicalIndex
int row = your_table->verticalHeader()->visualIndex(i);
if(item(row, Fruit))
return item(row, Fruit)->data(Qt::DisplayRole).value<QString>();
}

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.

How to get row number for a string in qtablewidget

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.

Fast search through QTableWidget rows

I need to search rows through a QTableWidget. Each of the rows in the table contains a field with date and I need to show only rows that are within a specified date interval based on user input. Here is my function:
void nvr::sort()
{
QTableWidget* tabela = this->findChild<QTableWidget*>("NCtable");
QDateEdit* c1 = this->findChild<QDateEdit*>("c1");
QDateEdit* c2 = this->findChild<QDateEdit*>("c2");
// user specified ranges for date
QDate date1 = c1->date();
QDate date2 = c2->date();
//row numbers in table
int rowsNum = tabela->rowCount();
// hide all rows
for(int z = 0; z < rowsNum; z++) {
tabela->hideRow(z);
}
// show only rows that are within range
for(int z = 0; z < rowsNum; z++) {
QDateTime dateTime = QDateTime::fromString(tabela->item(z,2)->text(),"dd.MM.yyyy hh:mm");
QDate date = dateTime.date();
//date compares
if ( (date1.operator <=(date)) && (date2.operator >=(date) ) ) {
tabela->showRow(z);
}
}
}
This works fine if i have 200 rows. But when i have 30 000 rows and i surely will, the gui freezes because i suppose the function executes very slow. Any suggestions for faster execution?
It is hard to reproduce your problem, but here is the approach I would take:
Create a custom class to store the data of one row, let's call it
DataRow.
Store those in a QVector<DataRow>, that you can sort by Date1 for example.
Loop through this QVector<DataRow> and find the elements that correspond to the criteria.
Add those DataRow to a class derived from QAbstractItemModel.
Show this model derived from QAbstractItemModel with a QTableView.
QTableWidget is heavyweight and was not really built for speed. It's really convenient to build something quickly with few elements though.
QTableView is the one you want, with a custom model inherited from QAbstractItemModel.
Then, when the user requests a new input, you could just wipe the model and restart the process. This is not optimal, but the user should not see the difference. Feel free to add more logic here to keep the good elements and only remove the bad ones.
About the GUI freezing, one way to always avoid that is to have the GUI thread separated from other worker threads. The QThread documentation is exhaustive and can help you set up something like this.

Filling column in List Contol with setItemText

I'm trying to fill my column in List control (m_listCtrl) in MFC. I want to do it in that way :
void CMy1domacanalogaRadixDlg::sort()
{
// some code here
for (int i = 0; i <size; i++)
{
counter++;
a[i] = b[i];
niz.Format(_T("%d"), a[i]);
// here choose column and add numbers
m_listCtrl.SetItemText(i,counter,niz);
}
}
I want to create columns dynamically, because I want to add every for loop iteration in own column, but the problem is that I need to press button "Sort" on my form twice to display numbers in column. It's all work fine, I have all numbers in column but not on first button press. Thanks for help.

How to populate wxListCtrl?

I'm trying to populate a wxListCtrl but after trying various methods can't seem to be able to populate it with items.
Basically, I want a list control that would have three columns with headings and will show values in rows. But I've tried InsertItem, SetItem, or InsertColumn methods but am only able to show the column headings but not the row data. Any help will be greatly appreciated! Thanks in advance!
You can add columns like this:
int column_width = 90;
my_list_ctrl->InsertColumn(0, L"ColumnText", wxLIST_FORMAT_LEFT, column_width);
You can add items like this:
int image_index = 0;
long list_index = my_list_ctrl->InsertItem(0, L"My Item text", image_index);
You can set the text of the subitems like this:
int column_index = 1;
my_list_ctrl->SetItem(list_index, column_index, L"Text");
You can setup an image list for your list like this:
my_list_ctrl->SetImageList(&img_list, wxIMAGE_LIST_SMALL);