PDA

View Full Version : Resize Pixmap to Fit Cell in QSqlTableModel



admkrk
20th April 2017, 02:51
Hi, I have a column that displays an image, but it is "cut off" where it is bigger than the cell size. I do not want to make the cell fit the image, just scale down the image, like a thumbnail. I have sub-classed QSqlTableModel and display the image in data() like this:

if(header == "Image")
{
QString link = QSqlTableModel::data(idx, Qt::DisplayRole).toString();
QPixmap pixmap(link);

switch(role)
{
case Qt::DisplayRole:
return QString();
break;
case Qt::DecorationRole:
return pixmap;
break;
case Qt::UserRole:
return link;
}
}
Is there some way to get the cell size, so I can return something like pixmap.scaled(cellSize), or find the lesser of scaledToHeigth() and scaledToWidth()? Or am I trying to go this in the wrong place?

I use images in a different column, but I am free to use small enough images that they fit. Ultimately, I plan to use the tool tip to show the image full sized.

Santosh Reddy
20th April 2017, 06:41
...Or am I trying to go this in the wrong place?...
Yes :)

Use QAbstractItemDelegate

admkrk
20th April 2017, 07:01
Thanks, I am using QStyledItemDelegate for the editor, but I assume it is mostly the same. I also assume I will need to use the paint function.

At least now I can look in the right direction.

d_stranz
20th April 2017, 21:34
At least now I can look in the right direction.

The thing that's tricky to understand about the Model / View architecture is that the model doesn't know anything about the view, its sizes, or anything else. You can have the same model displaying the same information in two totally different ways in different views. One of your views might show the pixmap as an icon, another might show it full-sized in a picture browser. It's up to the view to determine how to display the information served up by the model.

admkrk
21st April 2017, 01:42
It's up to the view to determine how to display the information served up by the model.
That makes it sound like I should be doing this with the view. I might be able to do that if I was only dealing with one table. In my case, I might be displaying a table that does not even contain that column.

I have figured out how to get the height and width from the delegate. Now I just need to figure out how the paint() function works.

d_stranz
21st April 2017, 20:32
Have you looked at the Star Delegate example (https://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html)?

admkrk
21st April 2017, 22:44
Among others, yes.

It looks like I also need to implement sizeHint(), along with paint(), and that is were I do the scaling. I should be able to figure it out once I start experimenting.

admkrk
22nd April 2017, 02:32
It looks like sizeHint() is not needed, after all. I have it working, for the most part.

void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QString header = model->headerData(index.column(),
Qt::Horizontal).toString();
if(header == "Image")
{
QString link = index.data().toString();
QPixmap pixmap(link);

pixmap = pixmap.scaled(option.rect.size(), Qt::KeepAspectRatio);

painter->drawPixmap(option.rect.topRight() / 2, pixmap);
}
else
QStyledItemDelegate::paint(painter, option, index);
}
The main problem I have now is that it is not quite centered. If my math is right, subtracting half the width of the pixmap should center it. Unfortunately, that is an int and I am not sure how to convert that to a QPoint. Time for more reading. :D

admkrk
23rd April 2017, 00:00
That seemed to work, until I went past the first row. Made a small change and it all seems to be working as intended now, just need to check different sized images and figure out why a relative path is not working.

void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QString header = model->headerData(index.column(),
Qt::Horizontal).toString();
if(header == "Image")
{
QString link = index.data().toString();
QPixmap pixmap(link);

pixmap = pixmap.scaled(option.rect.size(), Qt::KeepAspectRatio);
int centerCell = option.rect.width() / 2;
int centerPixmap = pixmap.width() / 2;

painter->drawPixmap(centerCell - centerPixmap, option.rect.y(),
pixmap);
}
else
QStyledItemDelegate::paint(painter, option, index);
}
Thanks all.