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
    #1

    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?

    JonBJ 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
      • ? A Former User

        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?

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #2

        @Gabber
        Why do you have two foreign keys, one in each table referencing the other?

        Why is Pilze.Galleriebild allowed to be NULL but Bilder.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 a NULL value.

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

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

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

            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?

            1 Reply Last reply
            0
            • ? A Former User

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

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #5

              @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/invalid QVariant() --- 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)....

              SGaistS 1 Reply Last reply
              0
              • JonBJ JonB

                @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/invalid QVariant() --- 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)....

                SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #6

                @JonB hi maybe you added a proxy model that returned a default value of the original was null ?

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

                JonBJ ? 2 Replies Last reply
                1
                • SGaistS SGaist

                  @JonB hi maybe you added a proxy model that returned a default value of the original was null ?

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #7

                  @SGaist
                  That sounds very possible, as I was thinking about it in my head earlier :)

                  Now if only you could get my Win 7 machine to still run its VirtualBox without crashing I could get back to look at my Linux Qt, but right now that's problematic. Sigh.

                  1 Reply Last reply
                  0
                  • SGaistS SGaist

                    @JonB hi maybe you added a proxy model that returned a default value of the original was null ?

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

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

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

                      Re-implement the data method and manage your special case there.

                      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
                      1
                      • SGaistS SGaist

                        Re-implement the data method and manage your special case there.

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

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

                        JonBJ 1 Reply Last reply
                        0
                        • ? A Former User

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

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #11

                          @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 of QVariant() (invalid/empty QVariant) or database NULL", 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 when index.data() returns QVariant(), 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 see paint() 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 NULLs.

                          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 contain NULL (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.

                          ? 1 Reply Last reply
                          1
                          • JonBJ JonB

                            @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 of QVariant() (invalid/empty QVariant) or database NULL", 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 when index.data() returns QVariant(), 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 see paint() 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 NULLs.

                            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 contain NULL (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.

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

                            @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 function setIdFilter, because there the emit 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.

                            JonBJ 1 Reply Last reply
                            0
                            • ? A Former User

                              @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 function setIdFilter, because there the emit 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.

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by JonB
                              #13

                              @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 its data(Qt::DisplayRole) to return "No image available" string when column is pixmap blob but has value NULL 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 your QDataWidegtMapper situation....

                              1 Reply Last reply
                              1
                              • ? 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

                                            • Login

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