Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available
-
Hello Community,
I have a problem but do not know where to start looking. Debugging unfortunately did not lead me to my result or I just missed it. The problem is as follows:
I have a QLabel in which I would like to display several images and switch through with a QToolButton. The images are in a database and are taken from the database via a QSqlTableModel. There is a second model in which I select a record. In addition, the associated should be displayed in the QLabel. This works quite well so far. Here is my code for it:
mainwindow.cpp
//Constructor of Mainwidow: Map Image to view //mImageFilterModel is a Custom QSortFilterProxyModel mImageMapper->setModel(mImageFilterModel); mImageMapper->setItemDelegate(new ImageDelegate(mImageMapper)); mImageMapper->addMapping(ui->imageView, mImageTableModel->fieldIndex("Bild"));
My ImageDelegate looks like this:
ImageDelegate::ImageDelegate(QObject *parent): QStyledItemDelegate(parent) {} ImageDelegate::~ImageDelegate() { qDebug() << "ImageDelegate deleted"; } void ImageDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QLabel *label = qobject_cast<QLabel *>(editor); if (label) { QByteArray imageData = index.data(Qt::EditRole).toByteArray(); QPixmap pixmap; if (pixmap.loadFromData(imageData)){ int width = label->width(); int height = label->height(); label->setPixmap(pixmap.scaled(width,height,Qt::KeepAspectRatio)); } } } void ImageDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QLabel *label = qobject_cast<QLabel *>(editor); if (label) { QBuffer buffer; buffer.open(QIODevice::WriteOnly); if (label->pixmap(Qt::ReturnByValue).save(&buffer)) model->setData(index, buffer.data(), Qt::EditRole); } }
After that I have made a function where I can select my data and then it will be mapped:
void MainWindow::dataIndexChanged(const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected); QModelIndex galleryImageIndex; QModelIndex index = selected.indexes().first(); int fungusId = mFungusTableModel->data(index.siblingAtColumn(0)).toInt(); int galleryImageId = mFungusTableModel->data(index.siblingAtColumn(8)).toInt(); mImageFilterModel->setIdFilter(fungusId); int numberOfImages = mImageFilterModel->rowCount(); for(int imageRow=0; imageRow<=numberOfImages; imageRow++){ QModelIndex imageIndex = mImageFilterModel->index(imageRow,0); if(!imageIndex.isValid()) break; int imageId = mImageFilterModel->data(imageIndex.siblingAtColumn(0)).toInt(); qDebug() << "ImageId: " << imageId; if(imageId == galleryImageId){ galleryImageIndex = mImageFilterModel->index(imageRow,0); break; } } qDebug() << "ID: " << fungusId; mDataMapper->setCurrentModelIndex(index); mImageMapper->setCurrentModelIndex(galleryImageIndex); }
The SQL relation looks like this from the two tables:
//Table Fungi CREATE TABLE "Pilze" ( "Id" INTEGER NOT NULL, "Name" TEXT NOT NULL UNIQUE, "Gattung" TEXT NOT NULL, "Art" TEXT NOT NULL, "Familie" TEXT, "Ordnung" TEXT, "Bemerkung" TEXT, "Gefaehrdung" INTEGER, "Galleriebild" INTEGER, PRIMARY KEY("Id"), FOREIGN KEY("Gefaehrdung") REFERENCES "Gefaehrdungsliste"("Id"), FOREIGN KEY("Galleriebild") REFERENCES "Bilder"("Id") ); //Table Images CREATE TABLE "Bilder" ( "Id" INTEGER NOT NULL, "Bild" BLOB NOT NULL, "Pilz_id" INTEGER NOT NULL, PRIMARY KEY("Id"), FOREIGN KEY("Pilz_id") REFERENCES "Pilze"("Id") );
And now the Problem: Everthing works as expected until I have no Image for the selected fungi record. The last selected image is displayed here.
However, I would like to have a simple text here like "No image available". Where and what do I need to change does anyone have a tip? -
I have found a way the whole thing seems to work. However, I don't know if it's clean or if it can lead to difficulties, since I'm working with Model / View. Maybe you two can take a look at it. Thanks for your active support!
void MainWindow::dataIndexChanged(const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected); QModelIndex galleryImageIndex; QModelIndex index = selected.indexes().first(); int fungusId = mFungusTableModel->data(index.siblingAtColumn(0)).toInt(); QByteArray galleryImage = mFungusTableModel->data(index.siblingAtColumn(8)).toByteArray(); mImageFilterModel->setIdFilter(fungusId); int numberOfImages = mImageFilterModel->rowCount(); if(numberOfImages != 0){ for(int imageRow=0; imageRow<=numberOfImages; imageRow++){ QModelIndex imageIndex = mImageFilterModel->index(imageRow,1); if(!imageIndex.isValid()){; break; } QByteArray image = mImageFilterModel->data(imageIndex.siblingAtColumn(1)).toByteArray(); if(image == galleryImage){ galleryImageIndex = mImageFilterModel->index(imageRow,0); break; } } mImageMapper->setCurrentModelIndex(galleryImageIndex); } else { ui->imageView->setText("No Image available"); } mDataMapper->setCurrentModelIndex(index); }
-
Hello Community,
I have a problem but do not know where to start looking. Debugging unfortunately did not lead me to my result or I just missed it. The problem is as follows:
I have a QLabel in which I would like to display several images and switch through with a QToolButton. The images are in a database and are taken from the database via a QSqlTableModel. There is a second model in which I select a record. In addition, the associated should be displayed in the QLabel. This works quite well so far. Here is my code for it:
mainwindow.cpp
//Constructor of Mainwidow: Map Image to view //mImageFilterModel is a Custom QSortFilterProxyModel mImageMapper->setModel(mImageFilterModel); mImageMapper->setItemDelegate(new ImageDelegate(mImageMapper)); mImageMapper->addMapping(ui->imageView, mImageTableModel->fieldIndex("Bild"));
My ImageDelegate looks like this:
ImageDelegate::ImageDelegate(QObject *parent): QStyledItemDelegate(parent) {} ImageDelegate::~ImageDelegate() { qDebug() << "ImageDelegate deleted"; } void ImageDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QLabel *label = qobject_cast<QLabel *>(editor); if (label) { QByteArray imageData = index.data(Qt::EditRole).toByteArray(); QPixmap pixmap; if (pixmap.loadFromData(imageData)){ int width = label->width(); int height = label->height(); label->setPixmap(pixmap.scaled(width,height,Qt::KeepAspectRatio)); } } } void ImageDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QLabel *label = qobject_cast<QLabel *>(editor); if (label) { QBuffer buffer; buffer.open(QIODevice::WriteOnly); if (label->pixmap(Qt::ReturnByValue).save(&buffer)) model->setData(index, buffer.data(), Qt::EditRole); } }
After that I have made a function where I can select my data and then it will be mapped:
void MainWindow::dataIndexChanged(const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected); QModelIndex galleryImageIndex; QModelIndex index = selected.indexes().first(); int fungusId = mFungusTableModel->data(index.siblingAtColumn(0)).toInt(); int galleryImageId = mFungusTableModel->data(index.siblingAtColumn(8)).toInt(); mImageFilterModel->setIdFilter(fungusId); int numberOfImages = mImageFilterModel->rowCount(); for(int imageRow=0; imageRow<=numberOfImages; imageRow++){ QModelIndex imageIndex = mImageFilterModel->index(imageRow,0); if(!imageIndex.isValid()) break; int imageId = mImageFilterModel->data(imageIndex.siblingAtColumn(0)).toInt(); qDebug() << "ImageId: " << imageId; if(imageId == galleryImageId){ galleryImageIndex = mImageFilterModel->index(imageRow,0); break; } } qDebug() << "ID: " << fungusId; mDataMapper->setCurrentModelIndex(index); mImageMapper->setCurrentModelIndex(galleryImageIndex); }
The SQL relation looks like this from the two tables:
//Table Fungi CREATE TABLE "Pilze" ( "Id" INTEGER NOT NULL, "Name" TEXT NOT NULL UNIQUE, "Gattung" TEXT NOT NULL, "Art" TEXT NOT NULL, "Familie" TEXT, "Ordnung" TEXT, "Bemerkung" TEXT, "Gefaehrdung" INTEGER, "Galleriebild" INTEGER, PRIMARY KEY("Id"), FOREIGN KEY("Gefaehrdung") REFERENCES "Gefaehrdungsliste"("Id"), FOREIGN KEY("Galleriebild") REFERENCES "Bilder"("Id") ); //Table Images CREATE TABLE "Bilder" ( "Id" INTEGER NOT NULL, "Bild" BLOB NOT NULL, "Pilz_id" INTEGER NOT NULL, PRIMARY KEY("Id"), FOREIGN KEY("Pilz_id") REFERENCES "Pilze"("Id") );
And now the Problem: Everthing works as expected until I have no Image for the selected fungi record. The last selected image is displayed here.
However, I would like to have a simple text here like "No image available". Where and what do I need to change does anyone have a tip?@Gabber
Why do you have two foreign keys, one in each table referencing the other?Why is
Pilze.Galleriebild
allowed to beNULL
butBilder.Pilz_id
is not?I don't know whether your database allows
NULL
in foreign key constraints.To get "simple text here like "No image available"" in a column cell which should be bound to showing an image I imagine you will need to do that in a delegate.
And I don't know who this ties with using a
QDataWidgetMapper
, where I think you are saying it will have to handle aNULL
value. -
@JonB said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
Why do you have two foreign keys, one in each table referencing the other?
Let me explain briefly why I built such a SQL construct. Each fungi can have none, one or more images. But each fungi has exactly one or no gallery image. Therefore Pilze.Galleriebild can also be NULL. Do I have a thinking error in the database?
@JonB said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
To get "simple text here like "No image available"" in a column cell which should be bound to showing an image I imagine you will need to do that in a delegate.
That's what I thought too. So I tried to debug my program. But if no image is stored, it doesn't jump into my ImageDelegate class at all. That's why I'm currently a bit at a loss how to proceed. Do you have a tip how I can continue?
-
I have revised my database schema. How I built the whole thing can be found here.
But now I still have the problem that when I select a record and there is no image stored for that record, it just shows me the last image.
Unfortunately the debugger does not jump into my ImageDelegate if the QModelIndex imageIndex has the following value: QModelIndex(-1,-1,0x0,QObject(0x0)). That is, if no index exists.
I would catch the whole thing in my ImageDelegate. But I don't understand why the debugger doesn't go in there. Any idea what I am doing wrong?
-
@JonB said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
Why do you have two foreign keys, one in each table referencing the other?
Let me explain briefly why I built such a SQL construct. Each fungi can have none, one or more images. But each fungi has exactly one or no gallery image. Therefore Pilze.Galleriebild can also be NULL. Do I have a thinking error in the database?
@JonB said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
To get "simple text here like "No image available"" in a column cell which should be bound to showing an image I imagine you will need to do that in a delegate.
That's what I thought too. So I tried to debug my program. But if no image is stored, it doesn't jump into my ImageDelegate class at all. That's why I'm currently a bit at a loss how to proceed. Do you have a tip how I can continue?
@Gabber said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
So I tried to debug my program. But if no image is stored, it doesn't jump into my ImageDelegate class at all.
I would catch the whole thing in my ImageDelegate. But I don't understand why the debugger doesn't go in there.
I have just remembered I have encountered this. When an item has no value at all ---
data(index)
returns empty/invalidQVariant()
--- the Qt framework does not call the delegate at all. As far as it is concerned there is nothing to show (which might be related to your "it just shows me the last image.").The trouble is, I do not recall what I did to achieve what you want (e.g. output a string when the SQL database returns
NULL
for the image).... -
@Gabber said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
So I tried to debug my program. But if no image is stored, it doesn't jump into my ImageDelegate class at all.
I would catch the whole thing in my ImageDelegate. But I don't understand why the debugger doesn't go in there.
I have just remembered I have encountered this. When an item has no value at all ---
data(index)
returns empty/invalidQVariant()
--- the Qt framework does not call the delegate at all. As far as it is concerned there is nothing to show (which might be related to your "it just shows me the last image.").The trouble is, I do not recall what I did to achieve what you want (e.g. output a string when the SQL database returns
NULL
for the image).... -
@JonB hi maybe you added a proxy model that returned a default value of the original was null ?
-
@JonB hi maybe you added a proxy model that returned a default value of the original was null ?
@SGaist Yes, I mapped a subclass QSortFilterProxyModel. My code:
#include "imagefiltermodel.h" ImageFilterModel::ImageFilterModel(){} ImageFilterModel::~ImageFilterModel() { qDebug() << "ImageFilterModel deleted"; } void ImageFilterModel::setIdFilter(const int &id) { if(mIdFilterValue != id) { mIdFilterValue = id; emit invalidateFilter(); } } bool ImageFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { Q_UNUSED(source_parent) if(mIdFilterValue == -1){ return true; } else { const int id = sourceModel()->index(source_row, mIdColumn).data().toInt(); return (id == mIdFilterValue); } }
The original model returns NULL. How can I proceed now? Do you have any tips? I am currently a bit overwhelmed and see no approach how I can continue. What I should look for or what I can try. Would be good if you could help me. Thanks for the support!
-
Re-implement the data method and manage your special case there.
-
@SGaist Implementing the data method doesn't seem to be correct either (at least I think). Here is my code first:
QVariant ImageFilterModel::data(const QModelIndex &index, int role) const { qDebug() << "DataIndex: " << index; if(!index.isValid()){ qDebug() << "Index in datamethod is invalid"; return QVariant(); } return QSortFilterProxyModel::data(index,role); }
In the first step I wanted to know if this method is really called. Therefore I just implemented a simple qDebug(). But here it goes again. If I select a dataset where no image is stored, then it does not jump into the data method. Can you help me please? Thanks a lot!
-
@SGaist Implementing the data method doesn't seem to be correct either (at least I think). Here is my code first:
QVariant ImageFilterModel::data(const QModelIndex &index, int role) const { qDebug() << "DataIndex: " << index; if(!index.isValid()){ qDebug() << "Index in datamethod is invalid"; return QVariant(); } return QSortFilterProxyModel::data(index,role); }
In the first step I wanted to know if this method is really called. Therefore I just implemented a simple qDebug(). But here it goes again. If I select a dataset where no image is stored, then it does not jump into the data method. Can you help me please? Thanks a lot!
@Gabber
I have now had a chance to fire up my Qt machine. But among my variety of projects I am unable to find "special handling ofQVariant()
(invalid/emptyQVariant
) or databaseNULL
", if I did have such a case.I do see the following in one project:
/*virtual*/ void BoardCellDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const /*override*/ { QVariant data(index.data()); if (!data.isValid()) { ...
That
!data.isValid()
test captures whenindex.data()
returnsQVariant()
, for "no value there". And this code is hit (and works) when certain cells do have "no data". So the implication is I find it does still call the delegate in this case....If you still find that is not the case, I think @SGaist's
@JonB hi maybe you added a proxy model that returned a default value of the original was null ?
would be: derive from
QIdentityProxyModel
, set its source to your model and add e.g.QVariant YourIdentityProxyModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const { if (!index.isValid()) return QVariant(); QVariant v(QIdentityProxyModel::data(index, role)); if (role == Qt::DisplayRole && index.column() == imageColumnNumber) if (!v.isValid()) v = "No image available"; return v; }
I think that ought work.
If you are still having problems:
- Temporarily remove your
QSortFilterProxyModel
and get it working without that. (This might even allow my earlier case above to work, where I do seepaint()
being called.) - I do not recognise your earlier
QModelIndex(-1,-1,0x0,QObject(0x0)). That is, if no index exists.
This is truly an invalid index, not invalid/empty/NULL data. Which is a different case, if Qt thinks an index is not valid it's not going to draw/output anything. Maybe that is all to do with your database foreign keys and
NULL
s.I would simplify your case while I figured out the behaviour/workaround for the no-image case you want to handle. Remove
QSortFilterProxyModel
, don't do foreign keys, have a database column just containNULL
(at least in certain rows). Reduce to a simple minimum, get that working like you want, then build up from there to your real case. - Temporarily remove your
-
@Gabber
I have now had a chance to fire up my Qt machine. But among my variety of projects I am unable to find "special handling ofQVariant()
(invalid/emptyQVariant
) or databaseNULL
", if I did have such a case.I do see the following in one project:
/*virtual*/ void BoardCellDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const /*override*/ { QVariant data(index.data()); if (!data.isValid()) { ...
That
!data.isValid()
test captures whenindex.data()
returnsQVariant()
, for "no value there". And this code is hit (and works) when certain cells do have "no data". So the implication is I find it does still call the delegate in this case....If you still find that is not the case, I think @SGaist's
@JonB hi maybe you added a proxy model that returned a default value of the original was null ?
would be: derive from
QIdentityProxyModel
, set its source to your model and add e.g.QVariant YourIdentityProxyModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const { if (!index.isValid()) return QVariant(); QVariant v(QIdentityProxyModel::data(index, role)); if (role == Qt::DisplayRole && index.column() == imageColumnNumber) if (!v.isValid()) v = "No image available"; return v; }
I think that ought work.
If you are still having problems:
- Temporarily remove your
QSortFilterProxyModel
and get it working without that. (This might even allow my earlier case above to work, where I do seepaint()
being called.) - I do not recognise your earlier
QModelIndex(-1,-1,0x0,QObject(0x0)). That is, if no index exists.
This is truly an invalid index, not invalid/empty/NULL data. Which is a different case, if Qt thinks an index is not valid it's not going to draw/output anything. Maybe that is all to do with your database foreign keys and
NULL
s.I would simplify your case while I figured out the behaviour/workaround for the no-image case you want to handle. Remove
QSortFilterProxyModel
, don't do foreign keys, have a database column just containNULL
(at least in certain rows). Reduce to a simple minimum, get that working like you want, then build up from there to your real case.@JonB Thank you very much for your answer. I can't derive from
QIdentityProxyModel
because I need filtering the model.My plan is to select an item from a QListView (the QListView is assigned a QSqlRelationTableModel). From there I get the ID of the record and search in my ImageFilterModel for the corresponding images and map them via the QDataWidgetMapper.
If I now derive my class from
QIdentityProxyModel
, then I no longer have the search functionsetIdFilter
, because there theemit invalidateFilter()
; no longer exists.I didn't think it would be so complicated. I'm sure I'm not the first to want something like this. Is there any other possibility? I definitely can't do without the filtration.
- Temporarily remove your
-
@JonB Thank you very much for your answer. I can't derive from
QIdentityProxyModel
because I need filtering the model.My plan is to select an item from a QListView (the QListView is assigned a QSqlRelationTableModel). From there I get the ID of the record and search in my ImageFilterModel for the corresponding images and map them via the QDataWidgetMapper.
If I now derive my class from
QIdentityProxyModel
, then I no longer have the search functionsetIdFilter
, because there theemit invalidateFilter()
; no longer exists.I didn't think it would be so complicated. I'm sure I'm not the first to want something like this. Is there any other possibility? I definitely can't do without the filtration.
@Gabber said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
I can't derive from QIdentityProxyModel because I need filtering the model.
I have no idea why you think this. You can. If necessary, and when working, you can have either of:
database -> QSqlTableModel -> QIdentityProxyModel -> QSortFilterProxyModel -> view database -> QSqlTableModel -> QSortFilterProxyModel -> QIdentityProxyModel -> view
Which one of these two depends on the exact behaviour you want for the "empty" image values. My initial preference would be for the second.
I merely suggested you remove the
QSortFilterProxyModel
temporarily while you get things working for the display of "No image" working, to simplify things.If I now derive my class from QIdentityProxyModel, then I no longer have the search function setIdFilter, because there the emit invalidateFilter(); no longer exists.
I don't understand what you mean by this. If it's relevant, don't forget that even if you use proxy models you can always access
sourceModel()
if you need to get at the original model for whatever reason.I reiterate: I do not recognise your
if the QModelIndex imageIndex has the following value: QModelIndex(-1,-1,0x0,QObject(0x0)). That is, if no index exists.
I don't know where you get that from, if I were you I would find out.
I didn't think it would be so complicated. I'm sure I'm not the first to want something like this. Is there any other possibility?
If you want to try out how it behaves with the very basic minimum of code, have you tried just deriving from
QSqlTableModel
and overriding itsdata(Qt::DisplayRole)
to return "No image available" string when column is pixmap blob but has valueNULL
instead of the blob/image? It's not ideal but maybe it will work for your "simple" desire? I don't know how that will relate to yourQDataWidegtMapper
situation.... -
@JonB said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
I reiterate: I do not recognise your
if the QModelIndex imageIndex has the following value: QModelIndex(-1,-1,0x0,QObject(0x0)). That is, if no index exists.
I had output this information from the following function via qDebug()). This appears exactly then if I select a data record with which no picture was deposited.
void MainWindow::dataIndexChanged(const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected); QModelIndex galleryImageIndex; QModelIndex index = selected.indexes().first(); int fungusId = mFungusTableModel->data(index.siblingAtColumn(0)).toInt(); QByteArray galleryImage = mFungusTableModel->data(index.siblingAtColumn(8)).toByteArray(); mImageFilterModel->setIdFilter(fungusId); int numberOfImages = mImageFilterModel->rowCount(); for(int imageRow=0; imageRow<=numberOfImages; imageRow++){ QModelIndex imageIndex = mImageFilterModel->index(imageRow,1); QModelIndex sourceIndex = mImageFilterModel->mapToSource(imageIndex); if(!imageIndex.isValid()){; break; } QByteArray image = mImageFilterModel->data(imageIndex.siblingAtColumn(1)).toByteArray(); if(image == galleryImage){ galleryImageIndex = mImageFilterModel->index(imageRow,0); break; } } mDataMapper->setCurrentModelIndex(index); mImageMapper->setCurrentModelIndex(galleryImageIndex); }
@JonB said in Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available:
database -> QSqlTableModel -> QIdentityProxyModel -> QSortFilterProxyModel -> view
database -> QSqlTableModel -> QSortFilterProxyModel -> QIdentityProxyModel -> viewOkay again for dummies to write down. I have now done the following.
I made a class called
ImageProxyModel
. This class looks like:#include "imageproxymodel.h" ImageProxyModel::ImageProxyModel(QObject *parent) : QIdentityProxyModel{parent} { } QVariant ImageProxyModel::data(const QModelIndex &index, int role) const { auto imageColumnNumber = 1; if(!index.isValid()) return QVariant(); QVariant v(QIdentityProxyModel::data(index, role)); if (role == Qt::DisplayRole && index.column() == imageColumnNumber) if (!v.isValid()) v = "No image available"; return v; }
So my
ImageFilterModel
class looks like this:#include "imagefiltermodel.h" ImageFilterModel::ImageFilterModel(){} ImageFilterModel::~ImageFilterModel() { qDebug() << "ImageFilterModel deleted"; } void ImageFilterModel::setIdFilter(const int &id) { if(mIdFilterValue != id) { mIdFilterValue = id; emit invalidateFilter(); } } bool ImageFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { Q_UNUSED(source_parent) if(mIdFilterValue == -1){ return true; } else { const int id = sourceModel()->index(source_row, mIdColumn).data().toInt(); return (id == mIdFilterValue); } }
In the constructor of the mainwindow.cpp I do the following:
mImageFilterModel = new ImageFilterModel; mImageProxyModel = new ImageProxyModel(this); mImageTableModel = mDatabaseManager->imageTableModel(); // mImageTableModel = QSqlRelationalTableModel mImageProxyModel->setSourceModel(mImageTableModel); mImageFilterModel->setSourceModel(mImageProxyModel); mImageMapper->setModel(mImageFilterModel); mImageMapper->setItemDelegate(new ImageDelegate(mImageMapper)); // mImageMapper = QDataWidgetMapper mImageMapper->addMapping(ui->imageView, mImageTableModel->fieldIndex("Bild"));
And my
ImageDelegate
class looks like this:ImageDelegate::ImageDelegate(QObject *parent): QItemDelegate(parent) {} ImageDelegate::~ImageDelegate() { qDebug() << "ImageDelegate deleted"; } void ImageDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QLabel *label = qobject_cast<QLabel *>(editor); if (label) { QByteArray imageData = index.data(Qt::EditRole).toByteArray(); QPixmap pixmap; if (pixmap.loadFromData(imageData)){ int width = label->width(); int height = label->height(); label->setPixmap(pixmap.scaled(width,height,Qt::KeepAspectRatio)); } } QItemDelegate::setEditorData(editor, index); } void ImageDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QLabel *label = qobject_cast<QLabel *>(editor); if (label) { QBuffer buffer; buffer.open(QIODevice::WriteOnly); if (label->pixmap(Qt::ReturnByValue).save(&buffer)) model->setData(index, buffer.data(), Qt::EditRole); } }
If I select a record from my QListView the function dataIndexChanged is called (see above).
Now the result of the current state: Image selection works as expected, but if no image is stored in the database, the last selected image remains stored in the QLabel instead of the text "No Image available".
So where is our thinking error? What have I possibly implemented incorrectly? Can you please look over it again?
Thanks for all the support! Without you I would be lost.
-
Hi,
You do not set the text on the label. You just change the image if you get a valid image.
-
Hi,
You do not set the text on the label. You just change the image if you get a valid image.
@SGaist
Can you please tell me in which function this is missing? Am slowly despairing... -
setEditorData
-
@SGaist
That is exactly my problem. When I select a data set from my QListView that does not contain an image, it no longer jumps into this function. -
Might be a silly question but how do you know that ?
-
@SGaist The debugger does not jump to this function. I can make a breakpoint in the setEditorData. As soon as I select a record with an image it jumps into the function and I can debug the whole thing. If I select a dataset that does not contain an image it does not jump into the setEditorData function.
Now the function currently looks like this and it still doesn't work.
void ImageDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QLabel *label = qobject_cast<QLabel *>(editor); if (label) { QByteArray imageData = index.data(Qt::EditRole).toByteArray(); QPixmap pixmap; if (pixmap.loadFromData(imageData)){ int width = label->width(); int height = label->height(); label->setPixmap(pixmap.scaled(width,height,Qt::KeepAspectRatio)); }else{ label->setText("Bla"); } } QItemDelegate::setEditorData(editor, index); }