PDA

View Full Version : Items in QListView should sort on Header Click



vinnu
30th October 2006, 11:59
Hai

I have a QListView where i have 2 headers by ID and Name.Id is handling only numeric items where as Name is handling alphanumeric.I have written a logic to sort the alphanumeric (using sorting) where as the same logic is effecting the numeric ones when both the single digits and multiple digits are there.The click on the ID is sorting the numbers this way(10,11,12,13,14,2,3,4,5 etc on one click and on other click this way :5,4,3,2,14,13,12,11,10).just like the strings the numeric are also sorted because here i have converetd the numerics to strings to map the correcssponding items because both the ID and Name are interrelated.

could anyone help me in sorting the Numerics on header click.

vinnu
2nd November 2006, 11:16
hai
once again i am back with the previous question with clear details wat i need exactly..
as i am not getting any response i am putting the question once again clearly

Hi, I have a little problem with a QListView:

I have a column that's a number and I want to sort the QListView by this
column. The problem is that the sorting of list is alfanumeric
because the column is a string and I want to sort 'numericaly' without
padding '0' before each number.

My Sorting The sort I want

1 1
10 2
11 3
12 4
13 5
14 6
2 7
3 8
4 9
5 10
6 11
... ...

I have no option of overriding compare because my parent class has been derived from QDialog and the dervived from QListview not from QListviewItem.
if i am using compare i am getting the build error as compare is not a member of QListview.

help is in urgent.

thanks for the help

bye
vinni

jacek
2nd November 2006, 19:47
Create your own QListViewItem subclass and reimplement QListViewItem::compare().

vinnu
3rd November 2006, 09:25
hai

cant i do it with out overriding compare.Is there any other way of sorting the numerics other than overriding comapare.

thanks for the help
vinnu

jacek
3rd November 2006, 10:32
cant i do it with out overriding compare.Is there any other way of sorting the numerics other than overriding comapare.
The easiest way is to reimplement QListViewItem::compare(), because that's what it was meant for, but you can also reimplement QListView::sort().

vinnu
3rd November 2006, 13:26
yes i have implemented it but it is not working for numerics .numerics are also getting sorted in the same way as that of strings.
i.e for example if i have values like 2,4,6,8,10,11,12,13,14,20,21....
when i click on column header it is sorting in this way.
10,11,12,13,14,2,20,21...which is exactly the string sort...
but i want it to get sorted in the numerics way...i.e 2,10,11,12,13,14,20,21....

can u plz help me...i am in great need of it.

thank u
vinnu

jacek
3rd November 2006, 13:35
yes i have implemented it but it is not working for numerics
How did you implement it?

vinnu
6th November 2006, 12:54
hai
buddy,I think u havent understand my problem clearly.

When i have used it numeric is working properly but alphanumerics are not sorting according to order.
I have 2 headers in which one is purely numeric(ID column) and other is alphanumeric(Name column).
by default i am able to sort the Numeric feild correctly.When i have written code for Alphanumeric type i.e using strcmp numeric feild have got disturb.these are getting sorted in the same way as string sorting(1,10,11,12,13,14,15,2,21,22,23,3,31,32.... .... )but i want in the order(1,2,3,10,11,12,13,14,15,21,22,23,24,31,32... ..).
So with out using QListView::sort() also i am able to sort the mumerics but the logic of strcmp for alphanumerics disturbed numeric sort.

thanks for the help...

vinnu

jacek
6th November 2006, 13:04
So with out using QListView::sort() also i am able to sort the mumerics but the logic of strcmp for alphanumerics disturbed numeric sort.
You need two sorting routines and you have to choose one depending on sortColumn() and sortOrder() values.

Everything would be much easier if you would reimplement QListViewItem::compare() since, QListView would handle the rest automatically.

vinnu
6th November 2006, 13:08
Hai

I dont have any derived class that is derived from QListviewitem and i have no oppurtunity of deriving the class from QLIstviewItem.I have a class derived from QLIstView and thats it.When i use compare i get the problem as "Compare is not a member of QListview".So without overriding compare do i have any other method.

When i have surfed the net i have got a solution of padding the items with zeros or spaces.so i have opted for spaces.
But i feel this is not the generic answer so looking out for other solutions other than this.

thanks
vinnu

jacek
6th November 2006, 13:16
I dont have any derived class that is derived from QListviewitem and i have no oppurtunity of deriving the class from QLIstviewItem.
Why? QListViewItem is meant to be subclassed.


When i use compare i get the problem as "Compare is not a member of QListview".
Because compare() is a method of QListViewItem, not QListView. If you want to reimplement compare(), then you have to subclass QListViewItem, not any other class.


But i feel this is not the generic answer so looking out for other solutions other than this.
If you really don't want to use QListViewItem::compare(), then you have to reimplement QListView::sort(), but do it properly --- check the value of QListView::sortColumn and sort either numerically or alphabetically.

vinnu
6th November 2006, 13:22
hai

OK...let me say my way of implementation....
i have written the connect stmt to the header click.


QHeader * pHeader = m_pBBListView->header();
connect(pHeader,SIGNAL(clicked(int)),this, SLOT(sortColumns(int)));

in Sortcolumn() i have added the following functionality.


void BBPickerDialog::sortColumns(int index)
{
BBPtr<BBStruct>listViewItemStruct(BBStruct::create("Item", "Item"));//it is our struct where we handle the our list view items//

QListViewItemIterator it( m_pBBListView );//m_pBBListview is member of BBpicker Dialog.
int valueIndex = (index == 0)?1:0;

PChar tempStr,tempStr2;

for ( ; it.current(); ++it)
{
QListViewItem *pItem = it.current();
QString key = pItem->text(index);
QString value = pItem->text(valueIndex);
sortList->addCopy(key.latin1());
listViewItemStruct->addStringField(key.latin1(),value);
}
for(size_t i=0;i<sortList->size();i++)
{
for(size_t j = i+1 ;j <sortList->size()-1;j++)
{
if(strcmp((*sortList)[i],(*sortList)[j])>0)
{
tempStr = strDup((*sortList)[i]);
tempStr2 = strDup((*sortList)[j]);
sortList->replaceItemAtIndex(i,tempStr2);
sortList->replaceItemAtIndex(j,tempStr);
}
}
}
QListViewItem *pLastItem = NULL;
m_pBBListView->clear();

for(size_t indx=0;indx<sortList->size();indx++)
{
BBPtr<BBString> value(listViewItemStruct->getStringField((*sortList)[indx]));
if(index==0)
pLastItem = new QListViewItem( m_pBBListView,(*sortList)[indx],value->asPChar());
else
pLastItem = new QListViewItem( m_pBBListView,value->asPChar(),(*sortList)[indx]);
}
}

u can understand my code ...

i think now u can understand my problem

jacek
6th November 2006, 14:53
u can understand my code ...
Unreadable code is a bad code.

First let's see how many lines of code it would take to implement it using QListViewItem::compare():

int CustomListViewItem::compare( QListViewItem * item, int col, bool ascending ) const
{
Q_UNUSED( ascending ); // ignored, like the docs recommend
if( col == 0 ) {
int a = text( col ).toInt();
int b = item->text( col ).toInt();
return (a - b);
}
else {
return QString::localeAwareCompare( text( col ), item->text( col ) );
}
}
See? It wasn't that hard.

Now for the sortColumns(). First of all you use QString::latin1(). What will happen with non-ASCII characters? And why do you delete all items, if you just need to reorder them? Why don't you reuse existing code?

I would do it this way:

class NumericalComparator
{
public:
NumericalComparator( int column ) : _column( column ) {}

bool operator()( const QListViewItem *a, const QListViewItem *b ) const
{
return ( ( a->text( _column ).toInt() - b->text( _column ).toInt() ) > 0 );
}

private:
int _column;
};

class StringComparator
{
public:
StringComparator( int column ) : _column( column ) {}

bool operator()( const QListViewItem *a, const QListViewItem *b ) const
{
return ( QString::localeAwareCompare( a->text( _column ), b->text( _column ) ) > 0 );
}

private:
int _column;
};

void BBPickerDialog::sortColumns(int index)
{
m_pBBListView->setUpdatesEnabled( false );

std::vector< QListViewItem * > items( m_pBBListView->childCount() );

for( QListViewItemIterator it( m_pBBListView ); it.current(); ++it ) {
items.push_back( it.current() );
}

if( index == 0 ) {
std::sort( items.begin(), items.end(), NumericalComparator( index ) );
}
else {
std::sort( items.begin(), items.end(), StringComparator( index ) );
}

for( std::vector< QListViewItem *>::iterator it = items.begin(); it != items.end(); ++it ) {
m_pBBListView->takeItem( *it );
m_pBBListView->insertItem( *it );
}

m_pBBListView->setUpdatesEnabled( true );
}
Now (provided that this code works, as I didn't test it) you can see that you don't need to copy anything, except for the pointers, and that you can easily reuse existing code (in this case from STL).

If you don't like STL, you can do a similar thing using QPtrList --- just subclass QPtrList<QListViewItem> and reimplement compareItems().

vinnu
7th November 2006, 08:44
Hai

Thank u .i will put it in my code and see whether it works or not and come to u again..

thanks a lot jaeck.

vinnu

vinnu
10th November 2006, 12:49
Hai jacek,

Thank u for ur help in time.I have approached my clients and said the problem and i have got the green signal to derive a class from QListviewItem and overide compare.It worked for me .

Thank u so much

bye
vinnu