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. QAbstractItemView::openPersistentEditor causes a performance deterioration

QAbstractItemView::openPersistentEditor causes a performance deterioration

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 6 Posters 1.9k Views 2 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.
  • F Offline
    F Offline
    Fran Sansone
    wrote on last edited by Fran Sansone
    #1

    I'm implementing a desktop application. Some of the widgets use a QTableView connected to a specialized model.

    I want to present some of the columns using a widget. So I subclassed QStyledItemDelegate and implemented this new widget. I want to show it all the time, not just when it's being edited, so I called openPersistentEditor for each row and column I needed.

    But this is causing a performance deterioration of about 20%. If I removes the lines that call openPersistentEditor, the performance deteriorarion is solved, so I assume this is causing the problem.
    Any ideas? One solution might be to override QStyledItemDelegate::paint, but it doesn't seem to be necessary considering that you can use openPersistentEditor. May I be doing something wrong?

    Some of the code:

    QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                                     const QModelIndex &index) const
    {
        QComboBox *view_selector = new QComboBox(parent);
        view_selector->setEditable(false);
        view_selector->setInsertPolicy(QComboBox::NoInsert);
    
        QStringList items = QStringList() <<  "item_1" << "item_2" << "item_3";
        view_selector->addItems(items);
    
        QModelIndex type_index = index.siblingAtColumn(ChannelsTableModel::COLUMN_TYPE);
    
        connect(view_selector, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
                &ComboBoxDelegate::commitEditor);
    
        return view_selector;
    }
    
    void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
    {
        QComboBox *view_selector = static_cast<QComboBox *>(editor);
        int index_value = index.data(Qt::DisplayRole).toInt();
    
        if (index_value >= 0 && index_value < view_selector->count()) {
            view_selector->setCurrentIndex(index_value);
        }
    }
    
    void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
    {
        QComboBox *view_selector = static_cast<QComboBox *>(editor);
        int index_value = view_selector->currentIndex();
        model->setData(index, index_value, Qt::DisplayRole);
    }
    
    void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                                         const QModelIndex &index) const
    {
        editor->setGeometry(option.rect);
    }
    

    And I'm calling openPersistentEditor in this way (column was previously defined):

    for (int i = 0; i < _table_model->rowCount(); ++i) {
            _table->openPersistentEditor(_proxy_model->index(i, column));
        }
    
    JonBJ 1 Reply Last reply
    0
    • F Fran Sansone

      I'm implementing a desktop application. Some of the widgets use a QTableView connected to a specialized model.

      I want to present some of the columns using a widget. So I subclassed QStyledItemDelegate and implemented this new widget. I want to show it all the time, not just when it's being edited, so I called openPersistentEditor for each row and column I needed.

      But this is causing a performance deterioration of about 20%. If I removes the lines that call openPersistentEditor, the performance deteriorarion is solved, so I assume this is causing the problem.
      Any ideas? One solution might be to override QStyledItemDelegate::paint, but it doesn't seem to be necessary considering that you can use openPersistentEditor. May I be doing something wrong?

      Some of the code:

      QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                                       const QModelIndex &index) const
      {
          QComboBox *view_selector = new QComboBox(parent);
          view_selector->setEditable(false);
          view_selector->setInsertPolicy(QComboBox::NoInsert);
      
          QStringList items = QStringList() <<  "item_1" << "item_2" << "item_3";
          view_selector->addItems(items);
      
          QModelIndex type_index = index.siblingAtColumn(ChannelsTableModel::COLUMN_TYPE);
      
          connect(view_selector, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
                  &ComboBoxDelegate::commitEditor);
      
          return view_selector;
      }
      
      void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      {
          QComboBox *view_selector = static_cast<QComboBox *>(editor);
          int index_value = index.data(Qt::DisplayRole).toInt();
      
          if (index_value >= 0 && index_value < view_selector->count()) {
              view_selector->setCurrentIndex(index_value);
          }
      }
      
      void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      {
          QComboBox *view_selector = static_cast<QComboBox *>(editor);
          int index_value = view_selector->currentIndex();
          model->setData(index, index_value, Qt::DisplayRole);
      }
      
      void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                                           const QModelIndex &index) const
      {
          editor->setGeometry(option.rect);
      }
      

      And I'm calling openPersistentEditor in this way (column was previously defined):

      for (int i = 0; i < _table_model->rowCount(); ++i) {
              _table->openPersistentEditor(_proxy_model->index(i, column));
          }
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @Fran-Sansone said in QAbstractItemView::openPersistentEditor causes a performance deterioration:

      I want to present some of the columns using a widget. So I subclassed QStyledItemDelegate and implemented this new widget. I want to show it all the time, not just when it's being edited, so I called openPersistentEditor for each row and column I needed.

      Well I'm sure "editing" has an overhead. Why do this, you should be able use a `QStyledItemDelegate" for items from a view for display as well as editing? ("One solution might be to override QStyledItemDelegate::paint, but it doesn't seem to be necessary" yes you should try this instead of putting into edit mode.)

      Having said that, if you have lots of these widgets there may be some hit. Many places only display an editing widget when actually editing. If he sees this @VRonin is your man in this area :)

      1 Reply Last reply
      1
      • Christian EhrlicherC Online
        Christian EhrlicherC Online
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Persistent editors are in the same category as index widgets (and under the hood it's the same) - try to avoid them and for sure don't add a lot of them. Use a custom QStyledItemDelegate instead.

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

        1 Reply Last reply
        3
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          If your custom widget is complex it might be worth using an intermediate solution like https://pastebin.com/XrppLZ3m

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          2
          • E Offline
            E Offline
            esmolikowski
            wrote on last edited by esmolikowski
            #5

            I am noticing a similar issue. I measure the cost of createEditor compared to the openPersistentEditor, and while it does take time, there seems to be a significant overhead in the openPersistentEditor outside of the createEditor itself. So say the sum of all the openPersistentEditor is 100ms only about 50ms of that is in the actual createEditor, the rest is in the overhead of openPersistentEditor. I am digging to find some more, because it is much more expensive than expected.

            Looking at the source code, there are 2 additional things that openPersistentEditor does besides createEditor. There is the visualRect() call and editor->show() call. There is also some overhead outside of openPersistenEditor like sizeHintForColumn() and sizeHintForRow(). I'm not sure what else yet.

            Would be nice to get some hints from Qt on this issue.

            Christian EhrlicherC JonBJ 2 Replies Last reply
            0
            • E esmolikowski

              I am noticing a similar issue. I measure the cost of createEditor compared to the openPersistentEditor, and while it does take time, there seems to be a significant overhead in the openPersistentEditor outside of the createEditor itself. So say the sum of all the openPersistentEditor is 100ms only about 50ms of that is in the actual createEditor, the rest is in the overhead of openPersistentEditor. I am digging to find some more, because it is much more expensive than expected.

              Looking at the source code, there are 2 additional things that openPersistentEditor does besides createEditor. There is the visualRect() call and editor->show() call. There is also some overhead outside of openPersistenEditor like sizeHintForColumn() and sizeHintForRow(). I'm not sure what else yet.

              Would be nice to get some hints from Qt on this issue.

              Christian EhrlicherC Online
              Christian EhrlicherC Online
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @esmolikowski said in QAbstractItemView::openPersistentEditor causes a performance deterioration:

              Would be nice to get some hints from Qt on this issue

              What do you want to hear? We already told you that you should avoid them. What T
              Qt version do you use? Please provide some code so we can reproduce it.

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

              1 Reply Last reply
              0
              • E esmolikowski

                I am noticing a similar issue. I measure the cost of createEditor compared to the openPersistentEditor, and while it does take time, there seems to be a significant overhead in the openPersistentEditor outside of the createEditor itself. So say the sum of all the openPersistentEditor is 100ms only about 50ms of that is in the actual createEditor, the rest is in the overhead of openPersistentEditor. I am digging to find some more, because it is much more expensive than expected.

                Looking at the source code, there are 2 additional things that openPersistentEditor does besides createEditor. There is the visualRect() call and editor->show() call. There is also some overhead outside of openPersistenEditor like sizeHintForColumn() and sizeHintForRow(). I'm not sure what else yet.

                Would be nice to get some hints from Qt on this issue.

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

                @esmolikowski said in QAbstractItemView::openPersistentEditor causes a performance deterioration:

                So say the sum of all the openPersistentEditor is 100ms only about 50ms of that is in the actual createEditor

                I don't understand what the real-world issue is. Opening an editor is probably invoked by a user action (like clicking something), maybe you just invoke it from code without that I can't be sure. Then the user has to interact with it to perform some editing operation. Even if there is a delay of a tenth or a twentieth of a second does that really affect the user experience?

                1 Reply Last reply
                1
                • E Offline
                  E Offline
                  esmolikowski
                  wrote on last edited by
                  #8

                  In order to have a pretty UI and make things more visible to our users, we openPersistentEditor for all QModelIndexes that have/need a custom widget. Say for example, I'd like to have a 'trash' button on each row to allow the user to delete a line item without going through a menu (think web style), we have a persistenEditor on each of those items.

                  SGaistS 1 Reply Last reply
                  0
                  • E esmolikowski

                    In order to have a pretty UI and make things more visible to our users, we openPersistentEditor for all QModelIndexes that have/need a custom widget. Say for example, I'd like to have a 'trash' button on each row to allow the user to delete a line item without going through a menu (think web style), we have a persistenEditor on each of those items.

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

                    @esmolikowski Hi,

                    Opening a persistent editor for a Trash button is typically a wrong use case. Create a custom QStyledItemDelegate to draw the button and handle the interaction.

                    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
                    • E Offline
                      E Offline
                      esmolikowski
                      wrote on last edited by
                      #10

                      That's exactly what I do. And for the editor to always visible, I use a persistent editor. I've got another case with a custom QLineEdit.

                      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