PDA

View Full Version : Searching a QTableView for a specific row



GreyGeek
5th December 2006, 21:30
Folks,
I am trying to create a method that can take a user's input and scan a QTableView object for a matching value in column 1. So far, my code is:


void supervisormaint::searchNames(){
QString findName = sui.leSearchText->text().trimmed();
QAbstractItemModel *modl = sui.EmployeesView->model();
QModelIndex curr = sui.EmployeesView->currentIndex();
int rc = modl->rowCount(curr.parent());
QString name;
QVariant vname;
QModelIndex rIndex;
for(int row = 0; row < rc; row++){
rIndex = modl->createIndex (row, 1, 0);
vname = modl->data(rIndex, 0);
name = vname.toString();
if (name.length() > 0 && name.contains(findName) == 0){
sui.EmployeesView->scrollTo(rIndex);
return;
}
}
QMessageBox::information(this,"Name Search:", findName + " NOT found!");
}

but my stumbling block is


rIndex = modl->createIndex (row, 1, 0);

which returns the compiler error:


'QAbstractItemModel::createIndex' : cannot access protected member declared in class 'QAbstractItemModel'

It appears that modl allows only for a single item index selected by the user.
I couldn't find a method to create an index array which would contain all 451 indexes that the view contains.

How do I do it?
:confused:

wysota
5th December 2006, 22:19
The shortest possible object oriented and nice code would be:

QString findName = sui.leSearchText->text().trimmed();
QAbstractItemModel *modl = sui.EmployeesView->model();
QSortFilterProxyModel proxy;
proxy.setSourceModel(modl);
proxy.setFilterKeyColumn(0);
proxy.setFilterFixedString(findName);
// now the proxy only contains rows that match the name
// let's take the first one and map it to the original model
QModelIndex matchingIndex = proxy.mapToSource(proxy.index(0,0));
if(matchingIndex.isValid(){
// ...
}
As for your code - simply substitute createIndex() with index() - you don't need to create an index, just ask the model to give you one.

GreyGeek
6th December 2006, 14:09
Wow, wysota, you must do "Mind Melds" with the API :)
I'm going to give you a new nickname: SPOCK!

Your proxy suggestion was fabulous! Much simpler, more elegant.

Here is the final version:


void supervisormaint::searchNames(){
QString findName = sui.leSearchText->text().trimmed();
QAbstractItemModel *modl = sui.EmployeesView->model();
QSortFilterProxyModel proxy;
proxy.setSourceModel(modl);
proxy.setFilterKeyColumn(1);
proxy.setFilterFixedString(findName);
// now the proxy only contains rows that match the name
// let's take the first one and map it to the original model
QModelIndex matchingIndex = proxy.mapToSource(proxy.index(0,0));
if(matchingIndex.isValid()){
sui.EmployeesView->scrollTo(matchingIndex,QAbstractItemView::EnsureVi sible);
} else {
QMessageBox::information(this,"Name Search:", "Match not found!");
}
}

wysota
6th December 2006, 21:52
Wow, wysota, you must do "Mind Melds" with the API

Thanks. If I only knew what "Mind melds" were :) To be honest, I look up to the best. Attending Trolltech DevDays in Munich this year (greetings to all the guys and girls (ok, one girl) I met there!) opened my eyes on some issues.


I'm going to give you a new nickname: SPOCK!
I feel my ears growing already. Live long and prosper! :cool:


Your proxy suggestion was fabulous! Much simpler, more elegant.

And a bit slower ;)

Note, that you can use the same code to implement a "progressive search" (in the "search when you write" way). You only need to connect a line edit's textChanged() signal to setFilterRegExp() of the proxy model.

QExcel(&ASAP)
20th March 2013, 12:51
Hello all. My doubt is that why do we need QModelIndex when we are setting the QSortFilterProxyModel::setSourceModel. I have tried without using QModelIndex and still I am able to find the string.

Qt code:
void filterPane::searchStr()
{
QString m_searchString = ui->cQIconLineEdit->text();
QSortFilterProxyModel proxy;
proxy.setSourceModel(alarmsModel);
proxy.setFilterRegExp(QRegExp(m_searchString, Qt::CaseInsensitive,
QRegExp::FixedString));
proxy.setFilterKeyColumn(2);
proxy.setFilterFixedString(m_searchString);

fp->hideWithEffect();
alarmPage *al = alarmPage::instance(&frame);
al->ui->AlarmsTable->setModel(&proxy);
}