Creating a QLineEdit Search Field for Items Displayed in a QListView

I want to create a search field that filters the items shown in a QListView. Basically, the user can enter "foo" and only items with "foo" in the DisplayRole will be shown.

I already have a few ideas on how to do this, but I thought that I would ask those who are more experienced than me.

My idea would be to use some signals and slots to set a filter in the QAbstractItem model and run update () in a QListView.

Are there any helper methods in QListView for filtering that I might have missed?

Is there a canonical way to handle this I have not come across?

change

Current progress.

I created a public slot called "updateFilter (QString)" in my subclass of QFileSystemModel. Then I

connect(myQLineEditSearch, SIGNAL(textChanged(QString)), myQFileSysModel, SLOT(updateFilter(QString))); 

This parameter sets the filter, then in my QFileSystemModel :: data (...) method I have:

  void ComponentModel::updateFilter(QString filter) { _filter = filter; emit layoutChanged(); } QVariant ComponentModel::data(const QModelIndex &index, int role) const { QVariant result; // if our search filter term is set and the item does not match, // do not display item data. Searches are case insensitive if (!_filter.isEmpty() && !QFileSystemModel::data(index, Qt::DisplayRole) .toString().toLower().contains(_filter.toLower())) { return result; } result = QFileSystemModel::data(index, role); return result; } 

It is almost that. The "crash" I'm working on is related to where the object is displayed. Currently, if I apply a search matching the 3rd item in the list, only the first two lines are displayed as empty. In other words, it still displays strings for inconsistent items.

+6
c ++ qt4
source share
3 answers

Answering my own question for reference.

It seems like a QSortFilterProxyModel is needed here.

The code looks something like this:

 QListView *myview = new QListView(this); MyModel *model = new MyModel(this); QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); proxy->setSourceModel(model); myview->setModel(proxy); myview->setRootIndex(proxy->mapFromSource(model->index(model->rootPath())); connect(filterLineEdit, SIGNAL(textChanged(QString)), proxy, SLOT(setFilterFixedString(QString))); 

The only problem I see in this is, apparently, rootIndex gets reset when entering a search string. I will update when I find out about this.

+5
source share

This will work for QListWidget ...

This method saves all elements found in a QList, from which you can later read them (for example, to show them in the same or new QListView):

 void search_for_string( QString search_str ) { QList<QListWidgetItem*> my_found_items; for( int i = 0; i < my_list->count(); i++ ) { QListWidgetItem* current = my_list->item( i ); if( current->text().contains( search_str ) ) { my_found_items.append( current ); } } } 

And when you click on "Search" or something else, you name it like this:

 search_for_string( my_line_edit->text() ); 
+3
source share

Another solution that works for QListWidget :

 void SpeciePropertiesListWidget::filter(QString filter_string) { hide_all(); QList<QListWidgetItem*> matches ( m_list->findItems(filter_string, Qt::MatchFlag::MatchContains) ); for(QListWidgetItem* item : matches) item->setHidden(false); } void SpeciePropertiesListWidget::hide_all() { for(int row(0); row < m_list->count(); row++ ) m_list->item(row)->setHidden(true); } 

And then plug in QLineEdit:

 QLineEdit * m_filter_le = new QLineEdit(this); SpeciePropertiesListWidget * list_widget = new SpeciePropertiesListWidget(this) connect(m_filter_le, SIGNAL(textEdited(QString)), list_widget, SLOT(refresh_filter(QString))); 
+2
source share

All Articles