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. Widget in my class does not set dirty the model
Forum Updated to NodeBB v4.3 + New Features

Widget in my class does not set dirty the model

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 2 Posters 5.0k 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.
  • P Offline
    P Offline
    Panoss
    wrote on last edited by Panoss
    #1

    I have a class named ImageLabel, extends QLabel.
    In it's constructor, I create a QPlainTextEdit:

    imagetext = new QPlainTextEdit(this);
    

    photo_lbl is a QLabel on my ui, promoted to ImageLabel.
    I map ui.photo_lbl and it's child imagetext, through my mapper (a QDataWidgetMapper), to a field:

    mapper->addMapping(ui.photo_lbl, photoIndex);
    mapper->addMapping(ui.photo_lbl->imagetext, photoIndex);
    

    The imagetext does take the data from the db field, up to this point everything is ok.
    But, when the text of imagetext changes, the model 's isDirty()...remains false!!!
    Why is this happening, how can I fix it?

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

      Hi,

      Out of curiosity, why do you have a QPlainTextEdit in a QLabel ?

      Did you saw that you are setting the same mapping twice but with different widgets ?

      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
      • P Offline
        P Offline
        Panoss
        wrote on last edited by
        #3

        Hi SGaist.
        I want to display a photo, it's a photo field.
        The label displays the photo.
        But somewhere I had to store the path of the photo.
        The label has no text property, so I added a textbox to hold it.
        Is there some better way to do it?

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

          Subclass QLabel and add a property that handles the QString for the path. Then use that QLabel and give the property name when setting up the mapper.

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

          P 1 Reply Last reply
          1
          • P Offline
            P Offline
            Panoss
            wrote on last edited by Panoss
            #5

            When I browse through the records, when I go from one record to next, textChanged Signal of the imagetext is triggered (because of the mapping).
            (let me remind you imagetext is a QPlainTextEdit)
            I use the textChanged Signal of the imagetext to refresh the label 's photo.

            connect(imagetext, SIGNAL(textChanged()),
                        this, SLOT(imagetextChanged()));
            

            If I remove the imagetext and replace it with a property, on which event shall I refresh the photo?

            1 Reply Last reply
            0
            • SGaistS SGaist

              Subclass QLabel and add a property that handles the QString for the path. Then use that QLabel and give the property name when setting up the mapper.

              P Offline
              P Offline
              Panoss
              wrote on last edited by
              #6

              @SGaist said in Widget in my class does not set dirty the model:

              Then use that QLabel and give the property name when setting up the mapper.

              What do you mean here?
              Something like:

              mapper->addMapping(ui.photo_lbl->myproperty, photoIndex);
              

              I think mapping can be done only on widgets, not on properties.

              1 Reply Last reply
              0
              • P Offline
                P Offline
                Panoss
                wrote on last edited by
                #7

                I ended up using two widgets on my form.
                A label, named photo_txt_lbl, which is subclassed and on it's dropEvent emits a custom signal, imageDropped:

                emit imageDropped();
                

                Then I connect the signal to a function that updates the second widget, a QPlainTextEdit named photo_txt:

                connect(ui.photo_txt_lbl,SIGNAL(imageDropped()),this, SLOT(photo_txt_textChanged()));
                

                the photo_txt 's textChanged signal is also connected to this function, which also updates the photo in the label.

                connect(ui.photo_txt,SIGNAL(textChanged()),this, SLOT(photo_txt_textChanged()));
                

                Complicated, but I couldn't find some better solution.

                1 Reply Last reply
                0
                • P Offline
                  P Offline
                  Panoss
                  wrote on last edited by
                  #8

                  Well, I just found something better:
                  my initial approach plus a custom signal like in my previous post, which sets the model data (model->setData), and so model gets dirty!

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

                    I was suggesting a real property like described here and if you take the overload of setMapping with three arguments, you can pass it the name of the property the mapper should use to interact with.

                    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
                    2
                    • P Offline
                      P Offline
                      Panoss
                      wrote on last edited by Panoss
                      #10

                      SGaist good morning.
                      You were right, I did it the way you suggested and works perfectly!!
                      Well, almost perfectly.
                      I still have to set the model 'manually' using the Signal imageDropped(which is emitted after image drop):
                      (now the imagetext() is a property)

                      connect(ui.photo_lbl,SIGNAL(imageDropped(QString)),this, SLOT(setModelPhoto(QString)));
                      
                      
                      .....................
                      }
                      
                      void RepairDevices::setModelPhoto(QString file)
                      {
                          model->setData(model->index(mapper->currentIndex(), photoIndex), file);
                      }
                      
                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Are you emitting the corresponding notify signal when the image changes ?

                        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
                        • P Offline
                          P Offline
                          Panoss
                          wrote on last edited by Panoss
                          #12

                          When I change it dropping an image:

                          void ImageLabel::dropEvent(QDropEvent *event)
                          {
                              ....blah blah blah...
                               QString mimeDataText = mimeData->text();
                                 
                               setImagetext(mimeDataText);
                               emit imageDropped(mimeDataText);
                          }
                          

                          In 2nd line, the setImagetext causes imagetextChanged to be emitted (in the setter( function setImagetext () )).
                          In line 3, signal imageDropped is emitted (this signal is used for 'manual' setData of the model).
                          You mean some of these two?

                          Or maybe this one:

                          Q_PROPERTY(QString Imagetext READ imagetext WRITE setImagetext NOTIFY imagetextChanged)
                          
                          1 Reply Last reply
                          0
                          • P Offline
                            P Offline
                            Panoss
                            wrote on last edited by Panoss
                            #13

                            Also when I load a photo with QFileDialog, I have to set the data for the model 'manually'.
                            I suppose I can't do something about this, right?

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

                              I meant imagetextChanged.

                              It will depend on how you load that photo after you used your dialog.

                              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
                              • P Offline
                                P Offline
                                Panoss
                                wrote on last edited by Panoss
                                #15

                                This is the code in the button that opens the QFileDialog:

                                void RepairDevices::on_insert_photo_btn_clicked()
                                {
                                    QString initialFolder = qApp->applicationDirPath() + QDir::separator() + "images";
                                    QString fileName = QFileDialog::getOpenFileName(this,
                                        tr("Load image"),initialFolder, tr("Image Files (*.png *.jpg *.bmp)"));
                                    ui.photo_lbl->setImagetext(fileName);
                                    
                                    model->setData(model->index(mapper->currentIndex(), photoIndex), fileName);
                                }
                                
                                1 Reply Last reply
                                0
                                • P Offline
                                  P Offline
                                  Panoss
                                  wrote on last edited by
                                  #16

                                  This is my class' header:

                                  #ifndef IMAGELABEL_H
                                  #define IMAGELABEL_H
                                  
                                  #include <QWidget>
                                  #include <QLabel>
                                  #include <qdebug.h>
                                  #include <QDragEnterEvent>
                                  #include <QDropEvent>
                                  #include <QMimeData>
                                  #include <QDebug>
                                  #include <QPixmap>
                                  
                                  class ImageLabel : public QLabel
                                  {
                                      Q_OBJECT
                                      Q_PROPERTY(QString Imagetext READ imagetext WRITE setImagetext NOTIFY imagetextChanged)
                                  
                                  public:
                                      ImageLabel(QWidget *parent = 0);
                                  
                                      QString Imagetext;
                                  
                                      void setImagetext(QString newValue);
                                      QString imagetext();
                                  
                                  
                                  signals:
                                      void imageDropped(QString file);
                                      void imagetextChanged(QString file);
                                  
                                  public slots:
                                  
                                  
                                  protected:    
                                      void dropEvent(QDropEvent *event) override;
                                      void dragEnterEvent(QDragEnterEvent *event) override;
                                      void dragMoveEvent(QDragMoveEvent *event) override;
                                      void dragLeaveEvent(QDragLeaveEvent *event) override;   
                                  
                                  private:
                                      QString m_imagetext;
                                  };
                                  
                                  #endif // IMAGELABEL_H
                                  

                                  This is the source:

                                  #include "imagelabel.h"
                                  
                                  ImageLabel::ImageLabel(QWidget *parent) :
                                      QLabel(parent)
                                  {
                                      setAcceptDrops(true);    
                                      m_imagetext="";
                                  }
                                  
                                  
                                  void ImageLabel::dropEvent(QDropEvent *event)
                                  {
                                      const QMimeData *mimeData = event->mimeData();
                                  
                                      if (mimeData->hasImage()) {
                                          setPixmap(qvariant_cast<QPixmap>(mimeData->imageData()));        
                                      } else if (mimeData->hasHtml()) {
                                          setText(mimeData->html());
                                          setTextFormat(Qt::RichText);       
                                      } else if (mimeData->hasText()) {
                                          setText(mimeData->text());
                                          setTextFormat(Qt::PlainText);
                                  
                                          // remove string "file:///" from mimeData->text()
                                          QString subStr = QLatin1String("file:///");
                                          QLatin1String newStr = QLatin1String("");
                                          QString mimeDataText = QString(mimeData->text().replace(mimeData->text().indexOf(subStr), subStr.size(), newStr));
                                  
                                          setImagetext(mimeDataText);
                                          emit imageDropped(mimeDataText);
                                  
                                      } else if (mimeData->hasUrls()) {
                                          QList<QUrl> urlList = mimeData->urls();
                                          QString text;        
                                          for (int i = 0; i < urlList.size() && i < 32; ++i)
                                              text += urlList.at(i).path() + QLatin1Char('\n');
                                          setText(text);
                                      } else {
                                          setText(tr("Cannot display data"));
                                      }
                                  
                                      setBackgroundRole(QPalette::Dark);
                                      event->acceptProposedAction();
                                  
                                  }
                                  
                                  void ImageLabel::dragEnterEvent(QDragEnterEvent *event)
                                  {    
                                      setBackgroundRole(QPalette::Highlight);
                                      event->acceptProposedAction();   
                                  }
                                  
                                  void ImageLabel::dragMoveEvent(QDragMoveEvent *event)
                                  {
                                      event->acceptProposedAction();
                                  }
                                  
                                  void ImageLabel::dragLeaveEvent(QDragLeaveEvent *event)
                                  {
                                      clear();
                                      event->accept();
                                  }
                                  
                                  void ImageLabel::setImagetext(QString newValue)
                                  {    
                                      m_imagetext = newValue;
                                  
                                      if(!m_imagetext.isEmpty()){
                                          QPixmap pixmap(m_imagetext);
                                          pixmap = pixmap.scaled(width(), height(), Qt::KeepAspectRatio);
                                          setPixmap(pixmap);
                                      }else{
                                          clear();
                                      }
                                      emit imagetextChanged(m_imagetext);
                                  }
                                  QString ImageLabel::imagetext()
                                  {
                                      return m_imagetext;
                                  }
                                  

                                  It's mapped through my custom property "Imagetext":

                                      mapper->addMapping(ui.photo_lbl, photoIndex, "Imagetext");
                                  

                                  When an image is dropped, the label sends a signal named 'imageDropped'.

                                  I use this signal to save the new value of the image path in the model:

                                      connect(ui.photo_lbl,SIGNAL(imageDropped(QString)),this, SLOT(setModelPhoto(QString)));
                                      .....................
                                      void RepairDevices::setModelPhoto(QString file)
                                      {
                                          model->setData(model->index(mapper->currentIndex(), photoIndex), file);
                                      }
                                  

                                  So this way I set the model 's data.

                                  I hope this helps.

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

                                    No directly related but your getter should rather be QString imagetext() const; and you should also rather const QString & in your setter.

                                    That will avoid needless copies.

                                    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
                                    • P Offline
                                      P Offline
                                      Panoss
                                      wrote on last edited by
                                      #18

                                      I made the changes you suggested SGaist, thanks.

                                      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