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. Unable to get selected rows/indexes in QTableView with custom model
Forum Updated to NodeBB v4.3 + New Features

Unable to get selected rows/indexes in QTableView with custom model

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 3 Posters 6.4k 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.
  • J Offline
    J Offline
    JohnGa
    wrote on 11 May 2019, 19:00 last edited by JohnGa 5 Nov 2019, 19:02
    #1

    Hello,
    I have a QTableView. I am trying to implement actions like Insert Above, Insert Below, Delete, etc. To implement these actions I need to know the selected rows in the table.

    Within the action handler, both the lines below return a collection size 0 (even though there are rows selected in the table):

    QModelIndexList selections = this->qTableView->selectionModel()->selectedIndexes();
    QModelIndexList selections1 = this->qTableView->selectionModel()->selectedRows();
    

    I am using a model that is subclass off of QAbstractTableModel.

    On the qTableView, I am also settings these attributes:

    this->qTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    this->qTableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    

    What am I doing wrong? How can I get the selected rows and their indexes in the model?

    Thanks

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 11 May 2019, 19:46 last edited by
      #2

      Hi,

      Can you show the implementation of your custom model ?
      What action handler is that ?
      Does it maybe clear the selection when called ?

      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
      • J Offline
        J Offline
        JohnGa
        wrote on 11 May 2019, 20:40 last edited by JohnGa 5 Nov 2019, 20:41
        #3

        Hi SGaist,
        I am overriding the following functions in my custom model (not sure if you need the internals):

        int rowCount(const QModelIndex &parent) const override;
            int columnCount(const QModelIndex &parent) const override;
            QVariant data(const QModelIndex &index, int role) const override;
            QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
            Qt::ItemFlags flags(const QModelIndex &index) const override;
            bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
            bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
            bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
            Qt::DropActions supportedDropActions() const override;
            bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
        

        I am installing a right-click customContextMenuRequested menu on the QTableView. To this QMenu, I add a QAction. The QAction is connected to a function in my class like this:

        connect(insertQuoteRowAbove, SIGNAL(triggered()), this, SLOT(insertQuoteRowAbove()));
        

        In the insertQuoteRowAbove function, I get empty collection when I call:

        QModelIndexList selections = this->qTableView->selectionModel()->selectedIndexes();
        QModelIndexList selections1 = this->qTableView->selectionModel()->selectedRows();
        

        Thanks

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 11 May 2019, 21:39 last edited by
          #4

          Then a maybe silly question but are you explicitly selecting a row before right clicking on it ?

          That said, you have the position of the mouse pointer given by the customContextMenuRequested signal, so you can use that to get the row under the mouse cursor.

          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
          • J Offline
            J Offline
            JohnGa
            wrote on 11 May 2019, 21:48 last edited by JohnGa 5 Dec 2019, 15:21
            #5

            Yes, even I select the row first, then right click on it, I still get empty collections when I execute the selectedRows and selectedIndexes on the selectionModel.

            With regards to your suggestion about using the position of the mouse pointer:
            I have both these lines:

            QModelIndex index = this->qTableView->indexAt(pos);
            

            and then

            contextMenu->popup(this->qTableView->viewport()->mapToGlobal(pos));
            

            I believe both of those are necessary. There are some inconsistencies in the column resolution, but the row resolution seems to be reliable. The problem I have taking this path is: How do I send the position or the QModelIndex into my insertQuoteRowAbove handler? Since the triggered signal does not have a QModelIndex parameter, I get the signal-slot mismatch error.

            connect(insertQuoteRowAbove, SIGNAL(triggered()), this, SLOT(insertQuoteRowAbove()));
            

            QUESTIONS:
            Is it cause for concern that my selectionModel is not tracking the selections? Any tips on how I can figure this out?

            Secondly, how do I get around the signal-slot mismatch if I have to go the route of passing the position/index?. I was able to figure out the answer to this question. signalmapper is the way to pass parameters into the slot. I am focussed on figuring out why my selectionModel is not tracking my selections.

            Thanks SGaist.

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 12 May 2019, 21:09 last edited by
              #6

              You can make that index a member of your class or use a lambda.

              Yes, it's pretty strange and you should investigate that.

              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
              • J Offline
                J Offline
                JohnGa
                wrote on 13 May 2019, 15:42 last edited by
                #7

                After setting up the Qt sources, I was able to debug into this problem. QtCreator and gdb are extremely unreliable. Debugging is like a minefield, bcos any one click could cause the debugger to exit.

                In any case, after stepping through the code, I could see that the selection was being applied in the selection model. When querying for the selectedRows or selectedIndexes the list was empty. It felt like I was accessing different selectionModels, and that is what the problem turned out to be. My cached selectionModel reference was not for the table that was being shown. Hence the empty selections.

                This was my stupid mistake. A stable debugging environment would make it so easy to find my own stupid mistakes. I fear that I will never has a stable debugging environment with Qt.

                R 1 Reply Last reply 26 Jun 2022, 06:34
                0
                • J JohnGa
                  13 May 2019, 15:42

                  After setting up the Qt sources, I was able to debug into this problem. QtCreator and gdb are extremely unreliable. Debugging is like a minefield, bcos any one click could cause the debugger to exit.

                  In any case, after stepping through the code, I could see that the selection was being applied in the selection model. When querying for the selectedRows or selectedIndexes the list was empty. It felt like I was accessing different selectionModels, and that is what the problem turned out to be. My cached selectionModel reference was not for the table that was being shown. Hence the empty selections.

                  This was my stupid mistake. A stable debugging environment would make it so easy to find my own stupid mistakes. I fear that I will never has a stable debugging environment with Qt.

                  R Offline
                  R Offline
                  Raghul Sekar
                  wrote on 26 Jun 2022, 06:34 last edited by
                  #8

                  @JohnGa Hi i'm woking on a similar project like your's if possible can u share your source code for right click in contextmenu to add row above , below

                  J 1 Reply Last reply 27 Jun 2022, 10:57
                  0
                  • R Raghul Sekar
                    26 Jun 2022, 06:34

                    @JohnGa Hi i'm woking on a similar project like your's if possible can u share your source code for right click in contextmenu to add row above , below

                    J Offline
                    J Offline
                    JohnGa
                    wrote on 27 Jun 2022, 10:57 last edited by JohnGa
                    #9

                    @Raghul-Sekar My questions above were the result of caching the selectionModel. I looked at the code and can't remember why I was caching the selectionModel. The key is NOT to cache references to the selectionModel. Any operations on the model, invalidates the existing selectionModel and creates a new one. Let's say you start out with a table that has rows 1,2,3,4. If you delete row 3, the selectionModel has to be emptied because the row does NOT exist anymore. The key is to query the underlying model for the selections after every model modification (this is because the indexes will shift after modifications to the underlying model).

                    Just like in regular data structures, one has to be careful when removing items in a collection. Let's say you have rows 1,2,3,4,5,6,7,8,9. Let's say you want to delete rows 3,5,7. Just like in regular data structures, if you delete row 3 first, then rows 5 & 7 are not at indexes 5 & 7. Therefore for multiple deletes, delete in reverse order. This is the same thing we do to avoid concurrent modification error.

                    That said, to insert below:
                    STEP 1: In your custom view:

                    QModelIndexList selections = this->selectionModel()->selectedRows();
                    

                    STEP 2: Reverse sort the selections (only needed if your table support multiple selections.
                    STEP 3: Iterate over the indexes and add to model:

                    for(int i = 0; i < selections.count(); i++)
                               {
                                   QModelIndex index = selections.at(i);
                                   qDebug() << "insertRowBelow row: " << index.row() << " column: " << index.column();
                                   this->model()->insertRows(index.row() + 1, 1, this->model()->index(0, 0));
                               }
                    

                    Using this approach you will be able to implement multi insert above/below, delete multiples, etc. Example: For insert above you would modify the params to the insertRows call.

                    1 Reply Last reply
                    2

                    • Login

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