PDA

View Full Version : Sorting in QTreeWidget



adhit
6th May 2007, 18:12
Hello!

QTreeWidget class has a function setSortingEnabled(bool), which provides us to sort items by clicking mouse button on the widget headers.
Does anybody know, how can I catch this event? When the user clicks mouse on the tree header I want to catch this event, and determine the sorting order. And then I will call my function, which will handle this event.

In short, how can I catch this event and define the sorting order?

wysota
6th May 2007, 18:24
You should take the model approach and reimplement the sort() method in the model.

adhit
6th May 2007, 18:57
You should take the model approach and reimplement the sort() method in the model.

Wysota, can yo tell me, how can I take the model approach?
Thanks!

marcel
6th May 2007, 19:21
QTreeWidget inherits QAbstractItemView, which has a method setModel( QAbstractItemModel * ).

You must subclass QAbstractItemModel and ( among others ) override its sort(...) method. Or maybe, depending on your needs you can subclass QStandardItemModel.

When you're done, use your model and set it using setModel.

Regards.

adhit
6th May 2007, 19:52
Marcel, but setModel(..) in QTreeWidget class is private.
Can I use QTreeView::setModel(..)?

So, you mean, that I need to create my own model with my own sort in this model, and then set this model to my tree?

Thanks!

bmesing
6th May 2007, 20:29
Marcel, but setModel(..) in QTreeWidget class is private.
Can I use QTreeView::setModel(..)?


You could use QTreeView, but there is no need for that in your case. Especially there is no need for overriding setModel().




So, you mean, that I need to create my own model with my own sort in this model, and then set this model to my tree?


Right.

Regards Ben

marcel
6th May 2007, 20:31
What do you mean it is private?
virtual void setModel (http://www.qtcentre.org/forum/qabstractitemview.html#setModel) ( QAbstractItemModel * model ) is public in QAbstractItemView, therefore public in QTreeVeiw and public in QTreeWidget.



So, you mean, that I need to create my own model with my own sort in this model, and then set this model to my tree?


Yes, you need to create your own mode and override the sort method.

Regards

wysota
6th May 2007, 20:32
You must subclass QAbstractItemModel and ( among others ) override its sort(...) method. Or maybe, depending on your needs you can subclass QStandardItemModel.
Go for QStandardItemModel or even use a proxy model and do the sorting there.



Marcel, but setModel(..) in QTreeWidget class is private.
Can I use QTreeView::setModel(..)?
No. You have to use QTreeView instead of QTreeWidget. QTreeWidget has an internal model and trying to set another model won't result in anything good.


So, you mean, that I need to create my own model with my own sort in this model, and then set this model to my tree?

Correct. Just make sure to emit proper signals (probably layoutChanged()) from within sort().

adhit
7th May 2007, 15:53
For example, I have:

// Class of new model
class TreeModel : public QStandardItemModel
{
Q_OBJECT
public:
TreeModel( QObject *parent = 0 );
protected:
void sort( int, Qt::SortOrder );
};

// class of the tree
class XMLTree : public QTreeWidget
{
Q_OBJECT
public:
XMLTree( QWidget *parent = 0 );
...
private:
TreeModel *_model;
...
};

TreeModel::TreeModel( QObject *parent )
:QStandardItemModel( parent )
{
}

void TreeModel::sort( int col, Qt::SortOrder order )
{
// My sorting
}

XMLTree::XMLTree( QWidget *parent )
:QTreeWidget( parent )
{
_model = new TreeModel( model() );
// ???
// How can I copy standard tree model properties to my model?
// I mean, that my model should be like standard model, but
// only with my sorting.
QTreeView::setModel( _model );
...
}


No. You have to use QTreeView instead of QTreeWidget. QTreeWidget has an internal model and trying to set another model won't result in anything good.

And... If I can't set new model to QTreeWidget, how can I override sorting in this situation?

Thanks!!!

jpn
7th May 2007, 16:34
You can do it fairly easily with the convenience view as well:


class MyTreeWidget : public QTreeWidget
{
Q_OBJECT

public:
MyTreeWidget(QWidget* parent = 0)
: QTreeWidget(parent)
{
// disable built-in sorting
setSortingEnabled(false);

// use our own sorting method instead
header()->setSortIndicatorShown(true);
header()->setClickable(true);
connect(header(), SIGNAL(sectionClicked(int)), this, SLOT(customSortByColumn(int)));
customSortByColumn(header()->sortIndicatorSection());
}

public slots:
void customSortByColumn(int column)
{
// here you can get the order
Qt::SortOrder order = header()->sortIndicatorOrder();

// and sort the items
sortItems(column, order);

// to get more control over actual sorting of items,
// reimplement QTreeWidgetItem::operator<()
}
};

adhit
7th May 2007, 16:50
jpn, THANK YOU VERY MUCH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :) :) :)

adhit
7th May 2007, 17:16
thank All Of You For Help!!! :)

wysota
7th May 2007, 19:59
Please don't shout. Thank you.

adhit
8th May 2007, 12:14
Hello, everyone!

I have parent item in the tree. This item has a list of children (QList<QTreeWidgetItem *>). How can I change the order of children in this list? I mean, how can I change the order manually, without using sortChildren() or clone()->takeChild()->insertChild().

Any ideas...

wysota
8th May 2007, 12:23
You don't need clone(). Just take the item and insert it elsewhere (I think you needn't even call takeTopLevelItem). I don't think there is a way to do it without taking items out (you can use qSwap() on dereferrenced pointers to exchange attributes of items, but then you'll have to implement the assignment operator properly).

adhit
8th May 2007, 12:49
wysota, thanks!

takeItem() - that's cool! At first, I used it only to delete item from the tree. But It also can take item and insert it in the new position.