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. QStyledItemDelegate::createEditor() not getting called
Forum Updated to NodeBB v4.3 + New Features

QStyledItemDelegate::createEditor() not getting called

Scheduled Pinned Locked Moved Solved General and Desktop
22 Posts 3 Posters 7.5k Views 3 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.
  • JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by JonB
    #1

    In my scenario, QStyledItemDelegate::createEditor() is not getting called when I double click on certain items in my QTableView. I am looking for a hint as to why not, please....

    Life is not simple, and nor is my scenario. I describe it in abstract, code would be large to reproduce. I am going to be brief as what I need is a clue as to where the issue lies.

    I have a proxy model derived from QIdentityProxyModel. It is a "semi-identity" model! Some columns are mapped to the underlying source model, but some columns are "internal" to my proxy model.

    I have done all the necessary overrides etc. Overridden methods include:

    columnCount();
    rowCount();
    data();
    setData();
    flags();
    mapFromSource();
    mapToSource();
    index();
    

    I have a QTreeView whose model is the proxy model. It has a setItemDelegate() to my delegate derived from QStyledItemDelegate. The delegate is for editing with spin boxes. It is taken from the Qt example for this. Overridden methods include:

    createEditor();
    setEditorData();
    setModelData();
    updateEditorGeometry();
    

    Now, everything works. All my mappings etc, correctly pick out indexes from the underlying source model or internal to the proxy model, as appropriate. data() picks out the right data, setData() sets the right data. And so on.

    If I double-click to edit a cell in a column mapped to the underlying source model it goes into spinbox edit mode on the correct thing, reads/writes it correctly, etc.

    Except only.... My problem is that if I double-click to edit a cell in a column mapped to the internal proxy model's data, nothing happens :( The subclassed QStyledItemDelegate::createEditor() simply does not get called, and that is where I am stuck.

    Now, you will immediately say, "Ah ha, that's because your flags must be wrong, it doesn't know it's editable". But for my proxy-internal editable columns I have:

    return (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled);
    

    This is what the flags for underlying source model return, I checked that. Note the Qt::ItemIsEditable. That code is indeed hit, and it shows the column in non-edit mode as not grayed for read-only, which it would if I removed that.

    So I need a clue: given that flags() is returning Qt::ItemIsEditable for an item, what else could be wrong/am I missing which would cause QStyledItemDeletegate::createEditor() not to be called??

    1 Reply Last reply
    1
    • JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by JonB
      #22

      For the sake of completeness, I present as the solution a complete, standalone, working code for this situation. For simplicity, I have removed any use of a QStyledItemDelegate for QTreeView::setItemDelegate() as this is not required.

      It shows the minimal needed to allow for a QAbstractProxyModel, derived from QIdentityProxyModel, where you want to combine data from an underlying genuine source model with additional data held in, or external to, the proxy model layer.

      I am marking this as the solution. Thanks to @Christian-Ehrlicher for all his hard work/solutions!

      #include <QApplication>
      #include <QDebug>
      #include <QIdentityProxyModel>
      #include <QStandardItemModel>
      #include <QTreeView>
      
      class MyProxyModel : public QIdentityProxyModel
      {
          int proxyData[5] = { 5, 6, 7, 8, 9 };
      
          virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override
          {
              Q_ASSERT(!parent.isValid());
              return 5;
          }
      
          virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override
          {
              Q_ASSERT(!parent.isValid());
              return 2;
          }
      
          virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
          {
              if (role == Qt::DisplayRole)
              {
                  if (orientation == Qt::Horizontal)
                      return QString("Column #%1 (%2)").arg(section).arg(section == 0 ? "source model" : "proxy model");
              }
              return QIdentityProxyModel::headerData(section, orientation, role);
          }
      
          virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
          {
              if (!index.isValid())
                  return QVariant();
              if (index.column() == 1)
              {
                  if (role == Qt::DisplayRole || role == Qt::EditRole)
                      return proxyData[index.row()];
                  return QVariant();
              }
              return QIdentityProxyModel::data(index, role);
          }
      
          virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
          {
              if (index.column() == 1)
              {
                  if (role == Qt::DisplayRole || role == Qt::EditRole)
                  {
                      proxyData[index.row()] = value.toInt();
                      return true;
                  }
                  return false;
              }
              return QIdentityProxyModel::setData(index, value, role);
          }
      
          virtual Qt::ItemFlags flags(const QModelIndex &index) const override
          {
              if (!index.isValid())
                  return Qt::NoItemFlags;
              if (index.column() == 1)
                  return (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled);
              return QIdentityProxyModel::flags(index);
          }
      
          virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
          {
              if (!sourceIndex.isValid())
                  return QModelIndex();
              Q_ASSERT(sourceIndex.column() == 0);
              return createIndex(sourceIndex.row(), 0);
          }
      
          virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
          {
              if (!proxyIndex.isValid())
                  return QModelIndex();
              if (proxyIndex.column() == 1)
                  return QModelIndex();
              Q_ASSERT(proxyIndex.column() == 0);
              return sourceModel()->index(proxyIndex.row(), 0);
          }
      
          virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
          {
              Q_ASSERT(!parent.isValid());
              QModelIndex proxyIndex = createIndex(row, column);
              if (proxyIndex.column() == 1)
                  return proxyIndex;
              return mapFromSource(mapToSource(proxyIndex));
          }
      
          virtual QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
          {
              if (!idx.isValid())
                  return QModelIndex();
              Q_ASSERT(!idx.parent().isValid());
              if (column == 1)
                  return index(row, column);
              return mapFromSource(sourceModel()->sibling(row, column, mapToSource(idx)));
          }
      
          virtual QModelIndex buddy(const QModelIndex &index) const override
          {
              return index;
          }
      };
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          QStandardItemModel *model;
          MyProxyModel *proxy;
          QTreeView *tv;
      
          model = new QStandardItemModel(5, 1);
          for (int row = 0; row < model->rowCount(); row++)
              model->setData(model->index(row, 0), row);
      
          proxy = new MyProxyModel;
          proxy->setSourceModel(model);
      
          tv = new QTreeView;
          tv->setModel(proxy);
          tv->show();
      
          return a.exec();
      }
      
      1 Reply Last reply
      1
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Try to override QStyledItemDelegate::paint() to see if your delegate is really used or maybe replaced by something else later on.

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        JonBJ 2 Replies Last reply
        0
        • Christian EhrlicherC Christian Ehrlicher

          Try to override QStyledItemDelegate::paint() to see if your delegate is really used or maybe replaced by something else later on.

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by JonB
          #3

          @Christian-Ehrlicher
          Hi Christian. I'll do that if you like, but I already know from breakpoints and other code in the delegate that it's being called all the time. In particular, remember that if the cell/item happens to be one mapped to the underlying source model rather than one that is mapped to the proxy's own data, createEditor() is called, is that not enough to prove?

          The delegate is set for the widget as a whole, via this->tableView->setItemDelegate(new MyDelegate(this));

          And it has an initStyleOption in which I alter option->text (for $ or % characters), and they show up fine on the proxy cells when in non-edit mode. So again that shows it's called for these proxy cells?

          I have just seen there is a QStyledItemDelegate::editorEvent, and QAbstractItemDelegate::editorEvent:

          When editing of an item starts, this function is called with the event that triggered the editing, the model, the index of the item, and the option used for rendering the item.

          The base implementation returns false (indicating that it has not handled the event).

          Maybe I should start looking there? I'm trying to understand what happens when it decides whether or not to call createEditor()?

          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #4

            @JonB said in QStyledItemDelegate::createEditor() not getting called:

            when it decides whether or not to call createEditor()?

            See QAIVP::editor() - so when this function gets called it should use your delegate...

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            JonBJ 1 Reply Last reply
            0
            • Christian EhrlicherC Christian Ehrlicher

              @JonB said in QStyledItemDelegate::createEditor() not getting called:

              when it decides whether or not to call createEditor()?

              See QAIVP::editor() - so when this function gets called it should use your delegate...

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

              @Christian-Ehrlicher
              Brill, thanks, I have stuff to look through over weekend!
              I have just had a haircut --- yay!!!!! [ When people read this in many years' time they will wonder how miraculous that was at this date :) ]

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

                Hi,

                One thing you can also do if you did not already is to add the override keyword to your overload declaration just in case there's a spelling or parameter issue.

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

                JonBJ 1 Reply Last reply
                0
                • SGaistS SGaist

                  Hi,

                  One thing you can also do if you did not already is to add the override keyword to your overload declaration just in case there's a spelling or parameter issue.

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

                  @SGaist
                  Thanks, they all have (virtual and) override on them, I like being thorough :) I annotated when pasting here.

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Christian Ehrlicher

                    Try to override QStyledItemDelegate::paint() to see if your delegate is really used or maybe replaced by something else later on.

                    JonBJ Online
                    JonBJ Online
                    JonB
                    wrote on last edited by
                    #8

                    @Christian-Ehrlicher said in QStyledItemDelegate::createEditor() not getting called:

                    Try to override QStyledItemDelegate::paint() to see if your delegate is really used or maybe replaced by something else later on.

                    FWIW, I have now had time to test this, and confirm it is indeed called, both on those elements which can be edited successfully and my problem ones which cannot.

                    1 Reply Last reply
                    0
                    • JonBJ Online
                      JonBJ Online
                      JonB
                      wrote on last edited by JonB
                      #9

                      Right! I have now had a chance to override my delegate's editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index).

                      • When double clicking on a cell mapped through the proxy to the underlying source model, which does go into edit mode, I see mouse up/down/click events with index being the correct, valid index into my proxy model. (Note: index has row/column/model being the proxy model, not the underlying source model.)

                      • When double clicking on a cell mapped into the proxy's own data, which does not go into edit mode, I see the same mouse events but with index being invalid --- row == -1, column == -1, model == QObject(0x0).

                      As I said, the mapFromSource(), mapToSource() & index() methods are all overridden to provide the correct mapping behaviour, e.g. in the non-edit case the correct data is displayed, taken from the underlying source model or from the proxy's own data as appropriate. I now need to understand what is different here, to cause the invalid index, which is obviously why it refuses to go into edit mode....

                      1 Reply Last reply
                      1
                      • JonBJ Online
                        JonBJ Online
                        JonB
                        wrote on last edited by JonB
                        #10

                        I have spent some time examining code, trying stuff out, etc., but to no avail. I have looked at the woboq source code of QIdentityProxyModel & QTransposeProxyModel, each of which has elements applicable to my model situation. I have come to the conclusion that there is simply not enough information, or I do not not understand enough, to reliably find a way forward. It may be that the necessary logic is there, or I need to override more methods, but I think I will just flounder, unable to identify the precise problem or progress.

                        Therefore, sadly, I think I must completely scrap my attempt to build a model based on QIdentity/TransposeProxyModel for my situation. It seems a shame as everything is working with the sole exception of the ability to make QStyledItemDeletegate::createEditor() work for interactive editing, but unless an expert can miraculously come up with the missing link I have little choice.

                        So I intend to give up on my model requiring some items to map to an underlying source model while other items have their data stored internally in the proxy model. Instead I will use a QStandardItemModel for the whole thing, which will give me model storage for non-source-model data, and override data() & setData() to access data local to QStandardItemModel for local items but call data()/setData() explicitly on the original source model for non-local data. And explicitly deal with model data change signals etc. At least I (should) know how to do that without issue....

                        1 Reply Last reply
                        0
                        • Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by
                          #11

                          Maybe you can strip it down so we can debug it.

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          JonBJ 1 Reply Last reply
                          0
                          • Christian EhrlicherC Christian Ehrlicher

                            Maybe you can strip it down so we can debug it.

                            JonBJ Online
                            JonBJ Online
                            JonB
                            wrote on last edited by JonB
                            #12

                            @Christian-Ehrlicher
                            Dear Christian,

                            You asked me to provide an example. I have slaved all morning to do so, so I hope you will very kindly care to examine it and provide feedback! :)

                            The code can be copied, compiled & run as-is. I have spent much time cutting it down to a minimum for pasting. there is much missing from my actual case, don't be surprised. I may have made some mistake/difference which is not present in my real, I don't know.

                            The intention is that the view/proxy model has 5 rows & 2 columns. Column #0 maps to column #0 of the QStandardItemModel source model. Column #1 maps to the internal proxy[] data array held "locally" in the proxy model.

                            The code behaves the same as real example, in that clicking column #0 does go into editor but clicking column #1 does not. That is my question. However, somewhere it is different from real case, but I don't know where. In my real example you would see clicking on column #1 does cause MyProxySpinDelegate::editorEvent() to be called, but with in invalid QIndex. In this cut down version it does not get called at all on column #1 click.

                            We will have to deal with that if we get as far as you suggesting how to make this one work to edit column #1 as well as column #0.

                            The code, all in main.cpp:

                            #include <QApplication>
                            #include <QDebug>
                            #include <QIdentityProxyModel>
                            #include <QSpinBox>
                            #include <QStandardItemModel>
                            #include <QStyledItemDelegate>
                            #include <QTreeView>
                            
                            class MyProxyModel : public QIdentityProxyModel
                            {
                                int proxyData[5] = { 5, 6, 7, 8, 9 };
                            
                                virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override
                                {
                                    Q_ASSERT(!parent.isValid());
                                    return 5;
                                }
                            
                                virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override
                                {
                                    Q_ASSERT(!parent.isValid());
                                    return 2;
                                }
                            
                                virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
                                {
                                    if (role == Qt::DisplayRole)
                                    {
                                        if (orientation == Qt::Horizontal)
                                            return QString("Column #%1 (%2)").arg(section).arg(section == 0 ? "source model" : "proxy model");
                                    }
                                    return QIdentityProxyModel::headerData(section, orientation, role);
                                }
                            
                                virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
                                {
                                    if (!index.isValid())
                                        return QVariant();
                                    if (index.column() == 1)
                                    {
                                        if (role == Qt::DisplayRole || role == Qt::EditRole)
                                            return proxyData[index.row()];
                                        return QVariant();
                                    }
                                    return QIdentityProxyModel::data(index, role);
                                }
                            
                                virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
                                {
                                    if (index.column() == 1)
                                    {
                                        if (role == Qt::DisplayRole || role == Qt::EditRole)
                                        {
                                            proxyData[index.row()] = value.toInt();
                                            return true;
                                        }
                                        return false;
                                    }
                                    return QIdentityProxyModel::setData(index, value, role);
                                }
                            
                                virtual Qt::ItemFlags flags(const QModelIndex &index) const override
                                {
                                    if (!index.isValid())
                                        return Qt::NoItemFlags;
                                    if (index.column() == 1)
                                        return (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled);
                                    return QIdentityProxyModel::flags(index);
                                }
                            
                                virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
                                {
                                    if (!sourceIndex.isValid())
                                        return QModelIndex();
                                    Q_ASSERT(sourceIndex.column() == 0);
                                    return createIndex(sourceIndex.row(), 0);
                                }
                            
                                virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
                                {
                                    if (!proxyIndex.isValid())
                                        return QModelIndex();
                            
                                    // I HAVE A FEELING NEXT 2 LINES MIGHT BE THE ROOT OF THE PROBLEM?
                                    // For proxy model colum #1, there is no index in the source model
                                    if (proxyIndex.column() == 1)
                                        return QModelIndex();
                            
                                    Q_ASSERT(proxyIndex.column() == 0);
                                    return sourceModel()->index(proxyIndex.row(), 0);
                                }
                            
                                virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
                                {
                                    Q_ASSERT(!parent.isValid());
                                    QModelIndex proxyIndex = createIndex(row, column);
                                    if (proxyIndex.column() == 1)
                                        return proxyIndex;
                                    return mapFromSource(mapToSource(proxyIndex));
                                }
                            };
                            
                                virtual QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
                                {
                                    if (!idx.isValid())
                                        return QModelIndex();
                                    Q_ASSERT(!idx.parent().isValid());
                                    if (column == 1)
                                        return index(row, column);
                                    return mapFromSource(sourceModel()->sibling(row, column, mapToSource(idx)));
                                }
                            
                            
                            class MyProxySpinDelegate : public QStyledItemDelegate
                            {
                                virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
                                {
                                    qDebug() << "editorEvent" << event->type() << model << option << index;
                                    return QStyledItemDelegate::editorEvent(event, model, option, index);
                                }
                            
                                virtual QWidget *createEditor(QWidget* parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
                                {
                                    Q_UNUSED(option);
                                    Q_UNUSED(index);
                                    QSpinBox *spin = new QSpinBox(parent);
                                    return spin;
                                }
                            };
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication a(argc, argv);
                                QStandardItemModel *model;
                                MyProxyModel *proxy;
                                QTreeView *tv;
                            
                                model = new QStandardItemModel(5, 1);
                                for (int row = 0; row < model->rowCount(); row++)
                                    model->setData(model->index(row, 0), row);
                            
                                proxy = new MyProxyModel;
                                proxy->setSourceModel(model);
                            
                                tv = new QTreeView;
                                tv->setModel(proxy);
                                tv->setItemDelegate(new MyProxySpinDelegate);
                                tv->show();
                            
                                return a.exec();
                            }
                            
                            1 Reply Last reply
                            1
                            • Christian EhrlicherC Offline
                              Christian EhrlicherC Offline
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on last edited by
                              #13

                              Looks like the default sibling() implementation is the culprit:

                              QModelIndex QIdentityProxyModel::sibling(int row, int column, const QModelIndex &idx) const
                              {
                                  Q_D(const QIdentityProxyModel);
                                  return mapFromSource(d->model->sibling(row, column, mapToSource(idx)));
                              }
                              

                              Since you don't have a col1 in your source model it will return an invalid index I would guess.

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              JonBJ 1 Reply Last reply
                              2
                              • Christian EhrlicherC Christian Ehrlicher

                                Looks like the default sibling() implementation is the culprit:

                                QModelIndex QIdentityProxyModel::sibling(int row, int column, const QModelIndex &idx) const
                                {
                                    Q_D(const QIdentityProxyModel);
                                    return mapFromSource(d->model->sibling(row, column, mapToSource(idx)));
                                }
                                

                                Since you don't have a col1 in your source model it will return an invalid index I would guess.

                                JonBJ Online
                                JonBJ Online
                                JonB
                                wrote on last edited by JonB
                                #14

                                @Christian-Ehrlicher
                                I'm not certain if you're saying I can correct this with my code?

                                I see that sibling() uses mapFromSource() & mapToSource(). I worry about whether my requirement can work.

                                Remember, what I have is a genuine source model with some genuine data columns for my special proxy model, but I also have columns of data internally in the proxy model.

                                In the case of Qt's QIdentityProxyModel & QTransposeProxyModel, both of them always map to/from data rows/columns in their source model.

                                In my case, I'm not worried about my mapFromSource(const QModelIndex &sourceIndex). An index in the source model can always be mapped to an index in my proxy (or invalid if not a mapped column).

                                But I am worried about mapToSource(const QModelIndex &proxyIndex). If the proxy index is column #0 I'm OK and can map to the source model. But if it's column #1, its own internal column, there is no source model index. And I think that is where there is a real problem? I can only return the proxyIndex parameter as-is, but that's an index in the proxy and I think may have caused infinite recursion error?, or QModelIndex() invalid. And I'm worried that is a problem either way round for the Qt code?

                                I have edited that fragment in my code above to read:

                                        // I HAVE A FEELING NEXT 2 LINES MIGHT BE THE ROOT OF THE PROBLEM?
                                        // For proxy model colum #1, there is no index in the source model
                                        if (proxyIndex.column() == 1)
                                            return QModelIndex();
                                
                                1 Reply Last reply
                                0
                                • Christian EhrlicherC Offline
                                  Christian EhrlicherC Offline
                                  Christian Ehrlicher
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #15

                                  @JonB said in QStyledItemDelegate::createEditor() not getting called:

                                  And I think that is where there is a real problem? I

                                  correct, reimplement sibling and implement a workaround for your special columns.

                                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                  Visit the Qt Academy at https://academy.qt.io/catalog

                                  JonBJ 1 Reply Last reply
                                  1
                                  • Christian EhrlicherC Christian Ehrlicher

                                    @JonB said in QStyledItemDelegate::createEditor() not getting called:

                                    And I think that is where there is a real problem? I

                                    correct, reimplement sibling and implement a workaround for your special columns.

                                    JonBJ Online
                                    JonBJ Online
                                    JonB
                                    wrote on last edited by JonB
                                    #16

                                    @Christian-Ehrlicher

                                    correct, reimplement sibling and implement a workaround for your special columns.

                                    But I don't think I know how to! (As in, what the code should do?)

                                    When idx is in the proxy model and refers to colum#1, there is no equivalent mapToSource(idx). Hmm, I want mapFromSource() of that .... Maybe in this case I need to just look up row, column in proxy model...?

                                    1 Reply Last reply
                                    0
                                    • Christian EhrlicherC Offline
                                      Christian EhrlicherC Offline
                                      Christian Ehrlicher
                                      Lifetime Qt Champion
                                      wrote on last edited by
                                      #17
                                      QModelIndex MyProxyModel::sibling(int row, int column, const QModelIndex &idx) const
                                      {
                                          if (column != 1)
                                            return mapFromSource(d->model->sibling(row, column, mapToSource(idx)));
                                        return <yourindexfor X,1>
                                      }
                                      
                                      

                                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                      Visit the Qt Academy at https://academy.qt.io/catalog

                                      JonBJ 2 Replies Last reply
                                      2
                                      • Christian EhrlicherC Christian Ehrlicher
                                        QModelIndex MyProxyModel::sibling(int row, int column, const QModelIndex &idx) const
                                        {
                                            if (column != 1)
                                              return mapFromSource(d->model->sibling(row, column, mapToSource(idx)));
                                          return <yourindexfor X,1>
                                        }
                                        
                                        
                                        JonBJ Online
                                        JonBJ Online
                                        JonB
                                        wrote on last edited by
                                        #18

                                        @Christian-Ehrlicher
                                        Yep, I get it now! The penny clicked as I typed it :) I will certainly try this tomorrow and report back!

                                        Thanks so much :)

                                        1 Reply Last reply
                                        0
                                        • Christian EhrlicherC Christian Ehrlicher
                                          QModelIndex MyProxyModel::sibling(int row, int column, const QModelIndex &idx) const
                                          {
                                              if (column != 1)
                                                return mapFromSource(d->model->sibling(row, column, mapToSource(idx)));
                                            return <yourindexfor X,1>
                                          }
                                          
                                          
                                          JonBJ Online
                                          JonBJ Online
                                          JonB
                                          wrote on last edited by JonB
                                          #19

                                          @Christian-Ehrlicher
                                          Dear Christian,

                                          Thank you for your suggestion. It does indeed make sense, but it still does not alter/solve the behaviour, either in the test code or in my real code :(

                                          I have incorporated your sibling override suggestion:

                                              virtual QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
                                              {
                                                  if (!idx.isValid())
                                                      return QModelIndex();
                                                  Q_ASSERT(!idx.parent().isValid());
                                                  if (column == 1)
                                                      return index(row, column);
                                                  return mapFromSource(sourceModel()->sibling(row, column, mapToSource(idx)));
                                              }
                                          

                                          I have also corrected a slip in my test code:

                                              virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
                                          

                                          (the default for role was wrong), and in editorEvent()

                                                  qDebug() << "editorEvent" << event->type() << model << option << index;
                                          

                                          (prints event->type()).

                                          I have edited my sample code above to include these three changes.

                                          I have verified that sibling() overrideis indeed called.

                                          The good news is that with the new sibling() definition the test code now acts like the real code, in that MyProxySpinDelegate::editorEvent() is called when clicking on the proxy-only column.

                                          However, the bad news is that in both test & real it still does not go into edit mode :( The debug from editorEvent() shows:

                                          • When clicking on a source-mapped column, which does go into edit mode, I see a bunch of lines starting:
                                          editorEvent QEvent::MouseButtonPress QIdentityProxyModel(0x5555557c2ef0) QModelIndex(0,0,0x0,QIdentityProxyModel(0x5555557c2ef0))
                                          
                                          • But on clicking the proxy-only column, which does not go into edit mode, I see the same bunch but with:
                                          editorEvent QEvent::MouseButtonPress QIdentityProxyModel(0x5555557c2ef0) QModelIndex(-1,-1,0x0,QObject(0x0))
                                          

                                          This invalid QModelIndex() must be the issue preventing going into edit mode successfully.

                                          Even with the sibling() change you should be finding the same as me, viz. it does not go into edit mode on proxy-only column? I don't know just how you came up with your observation, but can you not take it as far as actually making the test go into edit mode?

                                          1 Reply Last reply
                                          0
                                          • Christian EhrlicherC Offline
                                            Christian EhrlicherC Offline
                                            Christian Ehrlicher
                                            Lifetime Qt Champion
                                            wrote on last edited by
                                            #20

                                            The problem seems to be the QAIV::buddy() function (or better the reimplementation in QSFPM). Simply replace the implementation by

                                            QModelIndex buddy(const QModelIndex &index) const override
                                             {
                                                return index;
                                            }
                                            

                                            and the editing works as expected.

                                            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                            Visit the Qt Academy at https://academy.qt.io/catalog

                                            JonBJ 1 Reply Last reply
                                            1

                                            • Login

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