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. QTableView not updating despite attention to flags and explicit emit of dataChanged
Forum Updated to NodeBB v4.3 + New Features

QTableView not updating despite attention to flags and explicit emit of dataChanged

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 2.1k 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.
  • B Offline
    B Offline
    buckler
    wrote on last edited by SGaist
    #1

    Hello,
    My first forum post so hopefully I will be clear.
    I have an editable QTableView, or so I am trying to have.
    I can select and type in fields, and internal debug tells me that setData is being called and the model internal values are updated. I do emit dataChanged, or so I think I do, but the data function never gets called and the values don't change.

    Here is my model class:

    class workItemListViewingModel : public QAbstractTableModel
    {
      Q_OBJECT
    
    public:
      workItemListViewingModel(workItem *workItemParent) { parent = workItemParent; };
      int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
      int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
      QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
      QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
      bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
      Qt::ItemFlags flags(const QModelIndex & index) const Q_DECL_OVERRIDE { 
        return Qt::ItemIsSelectable |  Qt::ItemIsEditable | Qt::ItemIsEnabled | QAbstractTableModel::flags(index) | QAbstractItemModel::flags(index); 
      }
    
    signals:
    
    private:
      workItem *parent;
    };
    

    Note that I do not have any slots... this seems wrong to me, since I guess data is a slot? But none of the online examples show exploit indication of this. I have surmised it is due to the fact that the setData can actually trigger multiple data calls, with a range of cells rather than just the one it was called with, by setting this range on the emit call. (In fact I need to use this, so great.)

    Here is my setData code:

    bool workItemListViewingModel::setData(const QModelIndex & index, const QVariant & value, int role)
    {
      workItemListEntry entry = parent->workItemList().at(index.row());
      if (role == Qt::EditRole) {
        switch (index.column()) {
          case subjectID_col: { entry.setSubjectID(value.toString()); break; }
          case indication_col: { entry.setIndication(value.toString()); break; }
          default: {
            QErrorMessage *error = new QErrorMessage (0);
            error->showMessage(tr("Warning: Cannot edit this field in the application, need to change it at the source."));
            return false;
          }
        }
      }
      emit dataChanged(index,index);
      return true;
    }
    

    Can anyone help?

    Many thanks,
    Andy

    [edit: added missing coding tags ``` SGaist]

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

      Hi and welcome to devnet,

      No, setData is not a slot. You can see that in the documentation.

      As for your code, are you sure that setData is called for the Edit Role ? In any case, you are modifying the local copy of entry, not what you have in workItemList.

      On a side note, in your flags override, you should only call QAbstractTableModel::flags(index), that's the base class of your model.

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

      B B 2 Replies Last reply
      0
      • SGaistS SGaist

        Hi and welcome to devnet,

        No, setData is not a slot. You can see that in the documentation.

        As for your code, are you sure that setData is called for the Edit Role ? In any case, you are modifying the local copy of entry, not what you have in workItemList.

        On a side note, in your flags override, you should only call QAbstractTableModel::flags(index), that's the base class of your model.

        B Offline
        B Offline
        buckler
        wrote on last edited by
        #3

        @SGaist Thank you. Yes, I am sure that setData is being called, I have debug statement sheer. Entry is in workItem List; the table rows are entries, and the columns are fields in each entry.

        Here is a little more of the code to try to give more to go on, since I still have the problem.

        First is workItemListEntry class:
        class workItemListEntry
        {
        public:
        workItemListEntry() {};

        void setSubjectID(QString str) { subjectID = str; qDebug() << "in setSubjecId " << subjectID;};
        const QString getSubjectID() const { return subjectID; qDebug() << "in getSubjecId " << subjectID;};

        void setIndication(QString str) { indication = str; };
        const QString getIndication() const { return indication; };

        private:
        QString subjectID, indication;
        };

        and here is the "data" function in the model:
        QVariant workItemListViewingModel::data(const QModelIndex &index, int role) const
        {
        if (role == Qt::DisplayRole)
        {
        switch (index.column()) {
        case subjectID_col: return parent->workItemList().at(index.row()).getSubjectID();
        case indication_col: return parent->workItemList().at(index.row()).getIndication();
        (there are more cases and a default, but I am trying to simplify to focus on the issue)
        }
        }
        return QVariant();
        }

        The code which sets the model in the first place is in the constructor of an over-arching class which has the workItemList:
        workItem::workItem(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::workItem)
        {
        ui->setupUi(this);
        workItemListEntries.clear();
        (more in here, which sets up the list and gets the first view of the table coming out perfectly, before trying to edit it)
        workItemListViewingModel *wiListModel = new workItemListViewingModel(this);
        ui->workItemList->setModel( wiListModel );
        ui->workItemList->selectionModel()->selectedRows();
        ui->workItemList->verticalHeader()->setVisible(false);
        ui->workItemList->horizontalHeader()->setVisible(true);
        ui->workItemList->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        ui->workItemList->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

        }:

        the over-arching class, which is the one with the table view widget in it:
        class workItem : public QWidget
        {
        Q_OBJECT

        QString tabLabel;
        int sessionItemIndex;
        workItemListProvenance listProvenance;
        QList<workItemListEntry> workItemListEntries;

        public:
        explicit workItem(QWidget *parent = 0);
        ~workItem();
        Ui::workItem *ui;
        QList<workItemListEntry> &workItemList() { return workItemListEntries; };
        void setSessionItemIndex(int index) { sessionItemIndex = index; }
        void newWorkItemList();
        enum saveFormat { Json, Binary };
        bool loadWorkItemListFromFile(saveFormat saveFormat);
        bool saveWorkItemListToFile(saveFormat saveFormat) const;
        void readWorkItemList(const QJsonObject &json);
        void writeWorkItemList(QJsonObject &json) const;
        void logListProvenanceUpdate(QString step);

        public slots:
        QString getTabLabel() { return(tabLabel); }

        signals:
        void selectWorkItemButton_clicked(int sessionItemIndex);

        private slots:
        void on_selectWorkItemButton_clicked() { emit selectWorkItemButton_clicked(sessionItemIndex); }
        void on_targetPath_clicked() { QString pathFile=QFileDialog::getOpenFileName(this, tr("Path File"), "", tr("Path files (*.pth)")); };
        void on_seriesFolder_clicked() { QString seriesFolder=QFileDialog::getExistingDirectory(this, tr("Series Folder"), ""); };
        void on_seriesTypeSelector_activated(const QString &arg1) { std::cout << "selected " << std::endl; };
        void on_addWorkItemButton_clicked() {};
        void on_listFileNameButton_clicked() ;
        void on_labelTabsWithWorkItemID_clicked() { labelTabsWith = WORKITEMID; };
        void on_labelTabsWithPatientID_clicked() { labelTabsWith = PATIENTID; };
        void on_labelTabsWithPatientName_clicked() { labelTabsWith = PATIENTNAME; };
        void on_labelTabsWithSubjectID_clicked() { labelTabsWith = SUBJECTID; };
        void on_labelTabsWithAlsoKnownAs_clicked() { labelTabsWith = ALSOKNOWNAS; };

        private:
        QString workItemListFileName;
        enum field { WORKITEMID, PATIENTID, PATIENTNAME, SUBJECTID, ALSOKNOWNAS } labelTabsWith;
        };

        1 Reply Last reply
        0
        • SGaistS SGaist

          Hi and welcome to devnet,

          No, setData is not a slot. You can see that in the documentation.

          As for your code, are you sure that setData is called for the Edit Role ? In any case, you are modifying the local copy of entry, not what you have in workItemList.

          On a side note, in your flags override, you should only call QAbstractTableModel::flags(index), that's the base class of your model.

          B Offline
          B Offline
          bsomervi
          wrote on last edited by bsomervi
          #4

          In your setData overide:

          workItemListEntry entry = parent->workItemList().at(index.row());
          

          is making a copy so you are not updating your underlying data for your model.

          Try using:

          auto& entry = parent->workItemList()[index.row()];
          
          B 1 Reply Last reply
          1
          • B bsomervi

            In your setData overide:

            workItemListEntry entry = parent->workItemList().at(index.row());
            

            is making a copy so you are not updating your underlying data for your model.

            Try using:

            auto& entry = parent->workItemList()[index.row()];
            
            B Offline
            B Offline
            buckler
            wrote on last edited by
            #5

            @bsomervi wow... that is great. Of course I see it now, but would not have without your help. Both of you who replied! Thank you :-)

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

              You're welcome !

              Since you have it working now, please mark the thread as solved using the "Topic Tool" button so that other forum users may know a solution has been found :)

              Also, while browsing the forum, consider up-voting answers that helped you, it will make them easier to find for other forum users :)

              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

              • Login

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