PDA

View Full Version : setting size of a QListWidget to the width of its largest child



momesana
22nd September 2006, 10:00
Hi,
I am writing a preferences dialog that has a QListWidget on the left side and the settings buried in QTabWidgets and QWidgets positioned to the right of the listwidget. Now, when I open the prefs dialog, it divides the size of the dialog equally between the two widgets, but that is not what I want. I want the size of the QListWidget to be the size of the maximum QListWidgetItem it contains + a few percent. and resizing the dialog should give every extra space to the QTabWidgets/QWidgets. I can achieve this by setting the QListWidgets size to some static value like "120". This however should be problematic, if someone uses larger fonts etc. iterating through the QListWidgetItems and getting the maximum width by using QFontMetrics is also not the best solution since the outcome is rendered useless if I add a QIcon to the QListWidgetItem.



// set Size
QFontMetrics fm( font() );
int maxTextWidth;

for (int i=0; i<listWidget->count(); i++) {
qDebug() << listWidget->item(i)->sizeHint().width();
int x;
if ( (x = fm.width(listWidget->item(i)->text())) > maxTextWidth )
maxTextWidth = x;
};
listWidget->setMaximumWidth( maxTextWidth + maxTextWidth * 0.3 ); // add 30 percent to the size


The Items sizeHint() function returns -1 so I can't use it either. Can anyone tell me how to do it the right way?

Thanx in advance
momesana

high_flyer
22nd September 2006, 10:54
You should use layouts for that, a QHBoxLayout sound good for your case.
Also I don't think using setMaximumWidth for the QListWidget is good, since it only says what is the alowed maximum width, it will not neseseraly be that wide.
I'd use setWidth() for that.

jpn
22nd September 2006, 11:07
The Items sizeHint() function returns -1 so I can't use it either.
QListWidgetItem::sizeHint() returns the size hint which has been set. So if no size hint has been explicitly set, an invalid size hint is returned. You may ask the delegate to calculate a proper size hint for each item.


QListWidget::indexFromItem()
QAbstractItemView::itemDelegate()
QAbstractItemDelegate::sizeHint()

momesana
22nd September 2006, 12:36
QListWidgetItem::sizeHint() returns the size hint which has been set. So if no size hint has been explicitly set, an invalid size hint is returned. You may ask the delegate to calculate a proper size hint for each item.


QListWidget::indexFromItem()
QAbstractItemView::itemDelegate()
QAbstractItemDelegate::sizeHint()


I tried to follow your instructions and wrote this:


// set Size
int maxItemWidth = 0;

for (int i=0; i<listWidget->count(); i++) {

QModelIndex index = listWidget->indexFromItem(listWidget->item(i));
QAbstractItemDelegate * delegate = listWidget->itemDelegate();
QSize size = delegate->sizeHint( QStyleOptionViewItem (), index );

int x;
if ( ( x = size.width() ) > maxItemWidth )
maxItemWidth = x;
};
listWidget->setMaximumWidth( maxItemWidth );

Now, the compiler complains about listWidget::indexFromItem being protected... Do I really have to subclass the listWidget to be able to get the ModelIndex or is there a simpler way to achieve this?

Thanx in advance
momesana

jpn
22nd September 2006, 13:22
Now, the compiler complains about listWidget::indexFromItem being protected... Do I really have to subclass the listWidget to be able to get the ModelIndex or is there a simpler way to achieve this?
To get a model index, yes, you "have to". Why are people always so afraid of subclassing... ;)

momesana
22nd September 2006, 13:31
You should use layouts for that, a QHBoxLayout sound good for your case.
Also I don't think using setMaximumWidth for the QListWidget is good, since it only says what is the alowed maximum width, it will not neseseraly be that wide.
I'd use setWidth() for that.

A layout? Within a QListWidget? Afaik, QListWidgetItems cannot be put into a Layout anyway, since they do not inherit QWidget. http://doc.trolltech.com/4.2/hierarchy.html

Anyways, there is no setWidth() function that I could call on a QListWidget. The only possible values are setMinimumWidth or setMaximumWidth. setting both would be a solution here as well as setting setFixedWidth().

momesana
22nd September 2006, 14:00
To get a model index, yes, you "have to". Why are people always so afraid of subclassing... ;)
I subclassed it. The value returned by the delegates sizeHint() however also does not take into consideration the QIcon that I've added to the QWidgetItem. The effekt is the same as using a QFontMetric object to calculate the width of the item :(

Any further ideas?

Thanx
momesana

jpn
22nd September 2006, 14:03
You will have to pass a proper QStyleOptionViewItem. Try this:


QSize size = delegate->sizeHint(viewOptions(), index);

high_flyer
22nd September 2006, 14:03
A layout? Within a QListWidget? Afaik, QListWidgetItems cannot be put into a Layout anyway, since they do not inherit QWidget.
Oh?
Lets see:
QListWidget (the name already suggestes that it is a QWidget) inhertis QListView which inherits QAbstractItemView which inherits QAbstractScrollArea which inhertis QFrame which inherits QWidget.
Which by the way is exactly what you see in the link you posted.

So I don't see why not have a widget in a layout, specially when you want to implement a sizing policy on it.

Anyways, there is no setWidth() function that I could call on a QListWidget.
You are right about that, I didn't check it, I remembered wrong.
But my point stays the same, I'd use then setMinimumWidth() not maximum, since you want to assuere at least the width of the longest item in the list.

high_flyer
22nd September 2006, 14:07
I see where we missundertood each otoher.
I meant to put the QListWidget in to a Layout with the other widgest in your dialog, to have them use always the relative size (size policy) to each other.
I didn't understand that you were talking about QListWidgetItems in the QListWidget it self.
(sorry this was meant to be an EDIT in the previous post)

momesana
22nd September 2006, 23:14
I see where we missundertood each otoher.
I meant to put the QListWidget in to a Layout with the other widgest in your dialog, to have them use always the relative size (size policy) to each other.
I didn't understand that you were talking about QListWidgetItems in the QListWidget it self.
(sorry this was meant to be an EDIT in the previous post)
:) no problem. Big thanks for taking the time to read and answer to my post in the first place.

aurelien
21st February 2007, 12:26
I had to fix the same problem. I ended up implementing a function to compute the minimum width of a list view, and then constraining the view using setFixedWidth(myComputedWidth).

Here is the code of my function:


int computeListViewMinimumWidth(QAbstractItemView* view) {
int minWidth = 0;
QAbstractItemModel* model = view->model();

// Too bad view->viewOptions() is protected
// FIXME: Handle the case where text is below icon
QStyleOptionViewItem option;
option.decorationSize = view->iconSize();

int rowCount = model->rowCount();
for (int row = 0; row<rowCount; ++row) {
QModelIndex index = model->index(row, 0);
QSize size = view->itemDelegate()->sizeHint(option, index);
minWidth = qMax(size.width(), minWidth);
}
minWidth += 2 * view->frameWidth();
return minWidth;
}