Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 7

Qt-interest Archive, March 2007
QListBox and multiselection


Message 1 in thread

Hello,

I'm using  a qlistbox widget (qt3.3.4) with multiselection enabled.
I'm using following code to remove selected items:

[code]
...
idx = 0;
item = listbox->firstItem();
while ( item )
{
  if ( item->isSelected() )
  {
    // do something with this item
    listbox->removeItem( idx );
  }
  idx++;
  item = item->next();
}
...
[/code]

The result is, that the last highlighted item is not removed ( if they
are continous
selected ).

Another problem is, that if I select accidentaly more than those I
wanted, I move
the mouse back with left button pressed but the highlighted color
doesn't change.

Is this a bug with qlistbox?

Wolfgang

-- 
 [ signature omitted ] 

Message 2 in thread

Wolfgang Leideck wrote:
> I'm using  a qlistbox widget (qt3.3.4) with multiselection enabled.
> I'm using following code to remove selected items:
> 
> [code]
> ...
> idx = 0;
> item = listbox->firstItem();
> while ( item )
> {
>   if ( item->isSelected() )
>   {
>     // do something with this item
>     listbox->removeItem( idx );
>   }
>   idx++;
>   item = item->next();
> }
> ...
> [/code]
> 
> The result is, that the last highlighted item is not removed ( if they
> are continousselected ).

I have no Qt 3 installed anymore to actually check this, but
I wouldn't be surprised if QListBox::removeItem invalidated iterators
to the list, at least those 'pointing' to the removed item.

So the save way to remove itms should be to set up a sorted list of
indices to be removed and then remove them iterating through the list 
in decreasing order.

Andre'

--
 [ signature omitted ] 

Message 3 in thread

Well, I was falling in this problem too.
My solution is like that ( it's similiar to yours Tom):

[code]
QMap<int,int> itemIdx;

// get the list of selected items
QListBoxItem* item = listbox->firstItem();
int idx = 0;
while ( item )
{
    if ( item->isSelected() )
       itemIdx[idx++] = tabDefList->index( item );
    item = item->next();
}
// remove the items in reverse order
idx--;
while ( idx >= 0 )
{
    listbox->removeItem( itemIdx[idx--] );
}

This works for me.

Thanks for help
Wolfgang

2007/3/29, Tom Panning <lurchvt@xxxxxxxxx>:
> I ran your code, and in my tests it removes every other item. Part of your
> problem is that you're trying to maintain two different "pointers" to the
> same object; you assume that idx and item both refer to the same list item,
> but they could easily get out of sync. Secondly, as Wolfgang wrote, when
> you're removing elements from a list, it's best to traverse the list
> backwards. The reason is: lets say you decide to delete element 2, then what
> was element 3 becomes element 2, but if you increment your index, you will
> move on to the new element 3 (which used to be element 4), and so you can
> skip over elements quite easily. If you go through the list backwards, then
> removing an element will not affect the indexes that you haven't seen yet.
> Here is my code that seems to work properly:
>
>  for (int idx=listbox->count()-1; idx >= 0; idx--) {
>      if (listbox->item(idx)->isSelected()) {
>          listbox->removeItem(idx);
>      }
>  }
>
>  Hope that helps,
>  Tom

-- 
 [ signature omitted ]