PDA

View Full Version : Searching a QListWidget



bl1nk
8th August 2010, 18:24
I am trying to use a textbox that searches as you type. I have written some basic code that works perfect for smaller list, but not for big ones. I just connect this to the test edits changed signal. Is there anything I can do to speed this up?


QString searchText = ui->lineEdit->text();
int listWidgetSize = ui->listWidget->count();

for (int k1 = 0; k1 < listWidgetSize; k1++)
{
if (ui->listWidget->item(k1)->text().startsWith(searchText))
{
ui->listWidget->item(k1)->setHidden(false)
}
else
{
ui->listWidget->item(k1)->setHidden(true);
}
}


Thanks guys!

Lykurg
8th August 2010, 18:29
use
++k1in your for scope. But I guess you wont realize the speed improvement... Na you only can speed up, if you cache the widgets text in a QStringList or similar. But the best would be to use the model view frameworks. Look ups in models are really fast.

bl1nk
8th August 2010, 18:47
I would have to use a QListView to use the model frameworks right?

Lykurg
8th August 2010, 18:54
I would have to use a QListView to use the model frameworks right?
Yes, what data you are displaying right now? And how does it look like?

For searching see QSortFilterProxyModel.

bl1nk
8th August 2010, 19:02
Its basically just an image browser right now. In the list widget (icon view) i just have the image icon and the image name as the text. I have never use the model based framework. How do I go about adding data and accessing individual items?

Lykurg
8th August 2010, 19:17
For a beginning you can use QStandardItemModel with your text as display role and your image as decoration role. but the performance will be also not very well. If you want better performance you have to write your own model.

bl1nk
8th August 2010, 19:37
Alright, so for my list widget I was loading up all the icons with just a standard icon from a resource file. Then I start run a thread to go though and load the icons. That way it takes no time to load up the base icons, then just starts loading the actual image icons. I am having some trouble finding out how to access and individual item so that i can change its icon. How can I access and individual icon from the list view?

Ben1
9th August 2010, 12:48
I'm new but I want to know if when you set hidden an element, Qt redraw the QListWidget. If yes, that can explain the problem and using a copy of the widget can resolve the problem.

Just a note : ui->listWidget->item(k1)->setHidden(!ui->listWidget->item(k1)->text().startsWith(searchText))

bl1nk
9th August 2010, 20:21
Using the model view framework is a lot faster! I am using the proxy to search, but I am having issues filtering things that only start with the text. Should i use a regular expression to only take the first portion? What is the best way to go about this?

Also, with a list view how do you detect when the selection changes? (not clicking on anything) Like the QListWidget::currentItemChanged signal

Lykurg
9th August 2010, 20:43
Each view has a selection model with signals when the selection changes.
You can't access an icon of an item in a view. You have to set up your model. So if your thread have load an image set it to your model. This will emit a dataChanged signal and normally the view gets updated so that the new icon will be shown.
A regular expression is to much. I would go for startWith().

bl1nk
9th August 2010, 20:52
How do I use startWith() with my proxy? Thats what i cant figure out.

I have gotten the loading of the icons and everything working fine and have my model constructed. I just dont know how to detect when a selection change is made

Lykurg
9th August 2010, 21:54
Ok, first see this code from the docs:
bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent);

return (sourceModel()->data(index0).toString().contains(filterRegExp())
|| sourceModel()->data(index1).toString().contains(filterRegExp()))
&& dateInRange(sourceModel()->data(index2).toDate());
}
I guess your filter looks similar. so simple use something like:
sourceModel()->data(index0).toString().startsWith("foo")

For the selection change:
connect(pointerToYourView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(foo())); or use the selectionChanged signal etc.