Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available
Forum Updated to NodeBB v4.3 + New Features

Set text to QLabel if no Image from QSqlTableModel (QDataWidgetMapper) is available

Scheduled Pinned Locked Moved Solved General and Desktop
23 Posts 3 Posters 1.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #14

    @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 -> view

    Okay 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.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #15

      Hi,

      You do not set the text on the label. You just change the image if you get a valid image.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      ? 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

        You do not set the text on the label. You just change the image if you get a valid image.

        ? Offline
        ? Offline
        A Former User
        wrote on last edited by
        #16

        @SGaist
        Can you please tell me in which function this is missing? Am slowly despairing...

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #17

          setEditorData

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          ? 1 Reply Last reply
          0
          • SGaistS SGaist

            setEditorData

            ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #18

            @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.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #19

              Might be a silly question but how do you know that ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              ? 1 Reply Last reply
              0
              • SGaistS SGaist

                Might be a silly question but how do you know that ?

                ? Offline
                ? Offline
                A Former User
                wrote on last edited by A Former User
                #20

                @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);
                }
                
                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #21

                  What if you have only ImageProxyModel between your mapper and model ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  ? 1 Reply Last reply
                  0
                  • SGaistS SGaist

                    What if you have only ImageProxyModel between your mapper and model ?

                    ? Offline
                    ? Offline
                    A Former User
                    wrote on last edited by
                    #22

                    @SGaist
                    Now I have the follow in my constructor of mainwindow

                            mImageTableModel = 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.

                    1 Reply Last reply
                    0
                    • ? Offline
                      ? Offline
                      A Former User
                      wrote on last edited by
                      #23

                      @SGaist @JonB

                      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);
                      }
                      
                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved