Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available
-
@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); }
-
What if you have only ImageProxyModel between your mapper and model ?
-
@SGaist
Now I have the follow in my constructor of mainwindowmImageTableModel = mDatabaseManager->imageTableModel(); // mImageTableModel = QSqlRelationalTableModel mImageProxyModel->setSourceModel(mImageTableModel); mImageMapper->setModel(mImageProxyModel); mImageMapper->setItemDelegate(new ImageDelegate(mImageMapper)); // mImageMapper = QDataWidgetMapper mImageMapper->addMapping(ui->imageView, mImageTableModel->fieldIndex("Bild"));
And my dataIndexChanged method
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 = mImageProxyModel->rowCount(); // int numberOfImages = mImageFilterModel->rowCount(); for(int imageRow=0; imageRow<=numberOfImages; imageRow++){ QModelIndex imageIndex = mImageProxyModel->index(imageRow,1); // QModelIndex imageIndex = mImageFilterModel->index(imageRow,1); // QModelIndex sourceIndex = mImageFilterModel->mapToSource(imageIndex); if(!imageIndex.isValid()){; break; } // QByteArray image = mImageFilterModel->data(imageIndex.siblingAtColumn(1)).toByteArray(); QByteArray image = mImageProxyModel->data(imageIndex.siblingAtColumn(1)).toByteArray(); if(image == galleryImage){ // galleryImageIndex = mImageFilterModel->index(imageRow,0); galleryImageIndex = mImageProxyModel->index(imageRow,0); break; } } mDataMapper->setCurrentModelIndex(index); mImageMapper->setCurrentModelIndex(galleryImageIndex);
Unfortunately, this does not work. I am missing the filtering for the corresponding data set to display only the corresponding images.
-
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); }