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. qabstractitemmodeltester and editabletreemodel test failures

qabstractitemmodeltester and editabletreemodel test failures

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 3 Posters 948 Views
  • 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.
  • J Offline
    J Offline
    JohnGa
    wrote on last edited by JohnGa
    #1

    In qabstractitemmodeltester, the following test case is run when used on a tree model.
    qabstractitemmodeltester - SNIPPET 1:

    // Common error test #3, the second column should NOT have the same children
      // as the first column in a row.
      // Usually the second column shouldn't have children.
      if (model->hasIndex(0, 1)) {
          QModelIndex topIndex1 = model->index(0, 1, QModelIndex());
          MODELTESTER_VERIFY(topIndex1.isValid());
          if (model->hasChildren(topIndex) && model->hasChildren(topIndex1)) {
              QModelIndex childIndex = model->index(0, 0, topIndex);
              MODELTESTER_VERIFY(childIndex.isValid());
              QModelIndex childIndex1 = model->index(0, 0, topIndex1);
              MODELTESTER_VERIFY(childIndex1.isValid());
              MODELTESTER_VERIFY(childIndex != childIndex1);
          }
      }
    

    As per the editableTreeModel example, if the column is anything other than 0, the model returns an invalid index in the index method as shown below:
    editableTreeModel - SNIPPET 2:

    if (parent.isValid() && parent.column() != 0)
          return QModelIndex();
    

    Going back to the tester code above:
    In SNIPPET 1, childIndex1 will be invalid, because SNIPPET 2 returns an invalid index for all columns other than zero.
    If I remove the column 0 check in SNIPPET 2, then in SNIPPET 1 it fails on the last line because childIndex IS EQUAL TO childIndex.

    What is the right implementation here? Only when I return an index for all columns, the code seems to work correctly, but the model tester fails..

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

      So what's your actual implementation? The tester is correct. If the model says it has an index at index(x/y) then it should return a unique and valid one.

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

      J 1 Reply Last reply
      0
      • Christian EhrlicherC Christian Ehrlicher

        So what's your actual implementation? The tester is correct. If the model says it has an index at index(x/y) then it should return a unique and valid one.

        J Offline
        J Offline
        JohnGa
        wrote on last edited by
        #3

        @Christian-Ehrlicher Would it be possible for you to look at the editabletreemodel example that ships with QtCreator? When the model tester is applied to the example, it will fail with the failures above.

        Here are the steps to apply the modeltester to the editabletreemodel example:
        1)after the editabletreemodel example has been setup in QtCreator, open the editabletreemodel.pro file. Add "testlib" to the this line "QT += widgets ".
        2)Open mainwindow.cpp and add ```
        "#include <QAbstractItemModelTester>"
        3) Add the line shown below

        //The line below is in the example
        TreeModel *model = new TreeModel(headers, file.readAll());
        //Add the line below
        new QAbstractItemModelTester(model, QAbstractItemModelTester::FailureReportingMode::Fatal, this);
        

        4)Run the example and you will see the above failures.

        Thanks

        Christian EhrlicherC 1 Reply Last reply
        0
        • J JohnGa

          @Christian-Ehrlicher Would it be possible for you to look at the editabletreemodel example that ships with QtCreator? When the model tester is applied to the example, it will fail with the failures above.

          Here are the steps to apply the modeltester to the editabletreemodel example:
          1)after the editabletreemodel example has been setup in QtCreator, open the editabletreemodel.pro file. Add "testlib" to the this line "QT += widgets ".
          2)Open mainwindow.cpp and add ```
          "#include <QAbstractItemModelTester>"
          3) Add the line shown below

          //The line below is in the example
          TreeModel *model = new TreeModel(headers, file.readAll());
          //Add the line below
          new QAbstractItemModelTester(model, QAbstractItemModelTester::FailureReportingMode::Fatal, this);
          

          4)Run the example and you will see the above failures.

          Thanks

          Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by Christian Ehrlicher
          #4

          @JohnGa Thx, the columnCount() function is wrong (as already guessed in my first post). It must be
          int TreeModel::columnCount(const QModelIndex &parent) const
          {
          return parent.isValid() ? 0 : rootItem->columnCount();

          }

          int TreeModel::columnCount(const QModelIndex &parent) const
          {
              return (!parent.isValid() || parent.column() == 0) ? rootItem->columnCount() : 0;
          }
          

          -> only the first column has sub-columns, not the second (which would look somehow strange)

          It has no real-world impact in the Qt since the current implementation does first check for other things but is wrong when you want to catch all cases - the model tester is very picky here :). Will create a patch for it, thx.

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

          S 1 Reply Last reply
          3
          • Christian EhrlicherC Christian Ehrlicher

            @JohnGa Thx, the columnCount() function is wrong (as already guessed in my first post). It must be
            int TreeModel::columnCount(const QModelIndex &parent) const
            {
            return parent.isValid() ? 0 : rootItem->columnCount();

            }

            int TreeModel::columnCount(const QModelIndex &parent) const
            {
                return (!parent.isValid() || parent.column() == 0) ? rootItem->columnCount() : 0;
            }
            

            -> only the first column has sub-columns, not the second (which would look somehow strange)

            It has no real-world impact in the Qt since the current implementation does first check for other things but is wrong when you want to catch all cases - the model tester is very picky here :). Will create a patch for it, thx.

            S Offline
            S Offline
            StarterKit
            wrote on last edited by StarterKit
            #5

            Hi @Christian-Ehrlicher ,
            The topic is old, but my question exactly match the context of it so I decided to ask it here instead of creating a new topic.

            JohnGa gave a snippet of test case and my model fails at the last line:

            MODELTESTER_VERIFY(childIndex != childIndex1);
            

            I made it based on this example that hase following implementation of index() method:

            QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
            {
                if (!hasIndex(row, column, parent))
                    return QModelIndex();
            
                TreeItem *parentItem;
            
                if (!parent.isValid())
                    parentItem = rootItem;
                else
                    parentItem = static_cast<TreeItem*>(parent.internalPointer());
            
                TreeItem *childItem = parentItem->child(row);
                if (childItem)
                    return createIndex(row, column, childItem);
                return QModelIndex();
            }
            

            As I see the test do the following:
            Creates first top index model->index(0, 0, QModelIndex())
            Creates second top index model->index(0, 1, QModelIndex())
            So three are 2 indices (0, 0, <void>) and (0, 1, <void) but both have the same value of internalPointer as childItem depends on row only.
            As next step the test makes calls
            model->index(0, 0, topIndex) and model->index(0, 0, topIndex1) with different parent indices, but - both of them have the same internal pointer. So the call parentItem->child(row) will provide the same value of the childItem.
            And finally this return createIndex(row, column, childItem) will give two identical indices (0, 0, childItem) that will fail the test.

            But I don't fully understand what is wrong with all this story.
            My guess is that index() method should add childItem data only for column 0. But then parent() method of the example will fail. So I assume it should be changed to be more inteligente looking into internalPointer() of the first column. Is it right understanding or I miss something here?

            Christian EhrlicherC 1 Reply Last reply
            0
            • S StarterKit

              Hi @Christian-Ehrlicher ,
              The topic is old, but my question exactly match the context of it so I decided to ask it here instead of creating a new topic.

              JohnGa gave a snippet of test case and my model fails at the last line:

              MODELTESTER_VERIFY(childIndex != childIndex1);
              

              I made it based on this example that hase following implementation of index() method:

              QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
              {
                  if (!hasIndex(row, column, parent))
                      return QModelIndex();
              
                  TreeItem *parentItem;
              
                  if (!parent.isValid())
                      parentItem = rootItem;
                  else
                      parentItem = static_cast<TreeItem*>(parent.internalPointer());
              
                  TreeItem *childItem = parentItem->child(row);
                  if (childItem)
                      return createIndex(row, column, childItem);
                  return QModelIndex();
              }
              

              As I see the test do the following:
              Creates first top index model->index(0, 0, QModelIndex())
              Creates second top index model->index(0, 1, QModelIndex())
              So three are 2 indices (0, 0, <void>) and (0, 1, <void) but both have the same value of internalPointer as childItem depends on row only.
              As next step the test makes calls
              model->index(0, 0, topIndex) and model->index(0, 0, topIndex1) with different parent indices, but - both of them have the same internal pointer. So the call parentItem->child(row) will provide the same value of the childItem.
              And finally this return createIndex(row, column, childItem) will give two identical indices (0, 0, childItem) that will fail the test.

              But I don't fully understand what is wrong with all this story.
              My guess is that index() method should add childItem data only for column 0. But then parent() method of the example will fail. So I assume it should be changed to be more inteligente looking into internalPointer() of the first column. Is it right understanding or I miss something here?

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

              @DavidFaure knows maybe more on what's wrong here.

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

              S 1 Reply Last reply
              0
              • Christian EhrlicherC Christian Ehrlicher

                @DavidFaure knows maybe more on what's wrong here.

                S Offline
                S Offline
                StarterKit
                wrote on last edited by
                #7

                @Christian-Ehrlicher , I think I found how it works in the example. There is an additional restriction in rowCount() method of the model:

                int TreeModel::rowCount(const QModelIndex &parent) const
                {
                    if (parent.column() > 0)
                        return 0; 
                

                I.e. it simply reports no rows if asked for any column other than the left one. As result I assume there are no queries done for child indices outside the left column.

                Probably it is right... but not obvious...

                J 1 Reply Last reply
                0
                • S StarterKit

                  @Christian-Ehrlicher , I think I found how it works in the example. There is an additional restriction in rowCount() method of the model:

                  int TreeModel::rowCount(const QModelIndex &parent) const
                  {
                      if (parent.column() > 0)
                          return 0; 
                  

                  I.e. it simply reports no rows if asked for any column other than the left one. As result I assume there are no queries done for child indices outside the left column.

                  Probably it is right... but not obvious...

                  J Offline
                  J Offline
                  JohnGa
                  wrote on last edited by
                  #8

                  @StarterKit Yes, that "parent.column() > 0" check is necessary in the rowCount method. That is how I implemented it in all my TreeModels.

                  I do:
                  if(parent.isValid() && parent.column() > 0) return 0;

                  Hope that helps.

                  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