Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Using a custom data type and editor in QStandardItemModel

    General and Desktop
    3
    11
    1254
    Loading More Posts
    • 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.
    • L
      Lurkki last edited by

      I'm using a custom data type in the items of a QStandardItemModel, but setting item data for different roles seems to affect the data of all roles, and setting the text for the items seems to overwrite the data as well. What's the correct way of doing this?

      1 Reply Last reply Reply Quote 0
      • Christian Ehrlicher
        Christian Ehrlicher Lifetime Qt Champion last edited by

        How do you set the data? Please show some code.

        Qt has to stay free or it will die.

        L 1 Reply Last reply Reply Quote 0
        • L
          Lurkki @Christian Ehrlicher last edited by Lurkki

          @Christian-Ehrlicher
          Setting the data initially:

              std::function<void(tc_assignable_node_t*, QStandardItem*)> traverse;
              traverse = [=, &traverse](tc_assignable_node_t *node, QStandardItem *item) {
                  if (node == NULL) {
                      return;
                  }
                  
                  if (node->name != NULL) { 
                      qDebug() << node->name;
                  }
                  
                  // List for adding the name and editor on the same row
                  QList <QStandardItem*> rowItems;
                  
                  QStandardItem *nameItem = new QStandardItem;
                  nameItem->setText(node->name);
                  nameItem->setEditable(false);
                  rowItems.append(nameItem);
                  
                  // Don't add editor item for TC_ASSIGNABLE_NONE nodes
                  if (node->value_category != TC_ASSIGNABLE_NONE) {
                      QStandardItem *editorItem = new QStandardItem;
                      QVariant v;
                      AssignableData data(node);
                      v.setValue(data);
                      editorItem->setData(v, Qt::EditRole);
                      //editorItem->setText(node->name);
                      rowItems.append(editorItem);
                  }
                  
                  item->appendRow(rowItems);
                  
                  for (uint32_t i = 0; i < node->children_count; i++) {
                      traverse(node->children_nodes[i], nameItem);
                  }
              };
          

          setModelData() of my delegate:

              AssignableData data = qvariant_cast<AssignableData>(index.model()->data(index));
              QVariant v;
              QStandardItemModel *s_model = static_cast<QStandardItemModel*>(model);
          ...
          IntRangeEditor *ed = static_cast<IntRangeEditor*>(editor);
                              data.setValue(ed->value());
                              v.setValue(data);
                              s_model->setData(index, v, Qt::EditRole);
                              //s_model->itemFromIndex(index)->setText("");
          

          without the last line uncommented, it seems to overwrite the item's entire data and it becomes ineditable

          1 Reply Last reply Reply Quote 0
          • Christian Ehrlicher
            Christian Ehrlicher Lifetime Qt Champion last edited by

            @Lurkki said in Using a custom data type and editor in QStandardItemModel:

            without the last line uncommented,

            You mean '//s_model->itemFromIndex(index)->setText("");' ?
            This will set the Qt::DisplayRole and Qt::EditRole as explained in the documentation

            Qt has to stay free or it will die.

            L 1 Reply Last reply Reply Quote 1
            • L
              Lurkki @Christian Ehrlicher last edited by

              @Christian-Ehrlicher s_model->setData(index,"a", Qt::DisplayRole); has the same effect, it overwrites my custom data

              Christian Ehrlicher 1 Reply Last reply Reply Quote 0
              • mrjj
                mrjj Lifetime Qt Champion last edited by

                Hi
                I might have missed something but i only see you using
                Qt::EditRole
                so where is this custom data stored and in what way
                "becomes ineditable" its still shown but you can type in it or ?

                L 1 Reply Last reply Reply Quote 0
                • L
                  Lurkki @mrjj last edited by

                  @mrjj My mistake, yeah I can edit it but my custom data disappears. The data is stored in the model.

                  1 Reply Last reply Reply Quote 0
                  • Christian Ehrlicher
                    Christian Ehrlicher Lifetime Qt Champion @Lurkki last edited by

                    @Lurkki said in Using a custom data type and editor in QStandardItemModel:

                    has the same effect, it overwrites my custom data

                    I would say it's a bug if it's not - see the documentation...

                    Note: The default implementation treats Qt::EditRole and Qt::DisplayRole as referring to the same data.

                    Qt has to stay free or it will die.

                    L 1 Reply Last reply Reply Quote 0
                    • L
                      Lurkki @Christian Ehrlicher last edited by Lurkki

                      @Christian-Ehrlicher How should I go about subclassing QStandardItem and reimplementing setData then? I can't seem to find much information about it.

                      mrjj 1 Reply Last reply Reply Quote 0
                      • mrjj
                        mrjj Lifetime Qt Champion @Lurkki last edited by mrjj

                        @Lurkki

                        Hi
                        Can you please make a small example showing this ?,

                        I have a bad feeling its just incorrect use / expectations and
                        not an actual bug.

                        Qt::EditRole and Qt::DisplayRole is the same so that is expected.

                        try to use Qt::UserRole for your custom data end see.

                        To use custom data, you can use

                        setData(index,"a", Qt::UserRole );
                        setData(index,"a", Qt::UserRole +1);
                        setData(index,"a", Qt::UserRole +2);

                        L 1 Reply Last reply Reply Quote 2
                        • L
                          Lurkki @mrjj last edited by Lurkki

                          @mrjj Thanks, that works for my use case

                          Setting the data:

                                  if (node->value_category != TC_ASSIGNABLE_NONE) {
                                      QStandardItem *editorItem = new QStandardItem;
                                      QVariant v;
                                      AssignableData data(node);
                                      v.setValue(data);
                                      editorItem->setData(v, Qt::UserRole);
                                      //editorItem->setText(node->name);
                                      rowItems.append(editorItem);
                                  }
                          
                          

                          Setting editor data in the delegate:

                          void AssignableEditorDelegate::setEditorData(QWidget* editor, const QModelIndex &index) const {
                              AssignableData data = qvariant_cast<AssignableData>(index.model()->data(index, Qt::UserRole));
                              
                              switch (data.m_valueCategory) {
                                  case TC_ASSIGNABLE_RANGE:
                                      switch (data.m_rangeInfo.range_data_type) {
                                          case TC_ASSIGNABLE_RANGE_INT: {
                                              IntRangeEditor *ed = static_cast<IntRangeEditor*>(editor);
                                              ed->setValue(data.value().toInt());
                                              break;
                                          }
                                          default:
                                              break;
                                      }
                                  default:
                                      break;
                              }
                          }
                          

                          Setting model data:

                          void AssignableEditorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
                              AssignableData data = qvariant_cast<AssignableData>(index.model()->data(index, Qt::UserRole));
                              QVariant v;
                              QStandardItemModel *s_model = static_cast<QStandardItemModel*>(model);
                              
                              switch (data.m_valueCategory) {
                                  ...
                                  case TC_ASSIGNABLE_RANGE:
                                      switch (data.m_rangeInfo.range_data_type) {
                                          case TC_ASSIGNABLE_RANGE_INT: {
                                              IntRangeEditor *ed = static_cast<IntRangeEditor*>(editor);
                                              data.setValue(ed->value());
                                              v.setValue(data);
                                              s_model->setData(index, v, Qt::UserRole);
                                              s_model->setData(index, ed->value(), Qt::DisplayRole);
                                              break;
                                              }
                                          default:
                                              break;
                                      }
                                  default:
                                      break;
                              }
                          }
                          

                          I also had to do setAutoFillBackground(true); in my editor widget to make the display text not overlap with the editor.

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post