2010-04-23 17 views
6

Deseo crear un campo de búsqueda que filtre los elementos que se muestran en un QListView. Básicamente, el usuario puede escribir "foo" y solo se muestran los elementos con "foo" en DisplayRole.Creación de un campo de búsqueda QLineEdit para elementos visualizados en un QListView

ya tengo algunas ideas sobre cómo hacer esto, pero pensé en preguntar los más experimentados que yo

Mi idea sería utilizar algunas señales y ranuras para establecer un filtro en el modelo QAbstractItem y activa una actualización() en QListView.

¿Hay algún método de ayuda en QListView para el filtrado que pude haber omitido?

¿Hay una manera canónica de manejar esto que no he encontrado?

edición

progreso actual.

Creé una ranura pública llamada "updateFilter (QString)" en mi subclase QFileSystemModel. Entonces

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

Esto establece el filtro, entonces en mi QFileSystemModel :: método de datos (...), que tiene:

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; 
    } 

Esto es casi allí. El "error" en el que estoy trabajando tiene que ver con el lugar donde se muestra el objeto. Actualmente, si aplico una búsqueda que coincida con el tercer elemento de la lista, solo las primeras dos filas se mostrarán en blanco. En otras palabras, aún representa las filas para elementos no coincidentes.

Respuesta

5

responder a mi propia pregunta para referencia.

Parece que lo que se necesita aquí es un QSortFilterProxyModel.

El código es algo como:

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))); 

El único problema que estoy viendo en este es el rootIndex parece que se restablece cuando se introduce una cadena de búsqueda. Lo actualizaré cuando lo descubra.

3

Esto funcionaría para un QListWidget ...

Este método ahorra todos los elementos encontrados en una QList desde el que luego los puede leer (por ejemplo, para mostrar en el mismo o un nuevo 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); 
     } 
    } 
} 

Y cuando se pulsa en "Search" o lo que sea, usted lo llama así:

search_for_string(my_line_edit->text()); 
+1

Esto se ve bien, pero también se ve depende de que el usuario manualmente haciendo clic en un botón de búsqueda o algo así.Estoy tratando de obtener actualizaciones en vivo para la qlistview. Actualicé mi publicación para reflejar mi progreso actual. – jkyle

2

Otra solución que trabaja para una 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); 
} 

Y luego, conectar el 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))); 
Cuestiones relacionadas