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. Programmatically selecting next/prev row in QTableView skips rows
Forum Updated to NodeBB v4.3 + New Features

Programmatically selecting next/prev row in QTableView skips rows

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 2 Posters 2.6k 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.
  • P Offline
    P Offline
    patrickkidd
    wrote on last edited by
    #1

    While the up/down arrow key navigation defined in QAbstractItemView correctly navigate through the rows, the following code triggered from QAction skips rows which have the same value in column 0 when moving to the previous row (up) but not the next row (down). I haven't had much success debugging the model code who sorts by that same column zero.

        def selectNextEvent(self):
            indexes = self.selectionModel().selectedIndexes()
            if indexes:
                index = self.model().index(indexes[0].row() + 1, indexes[0].column())
            else:
                index = self.model().index(0, 0)
            self.selectionModel().select(index, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
    
        def selectPrevEvent(self):
            indexes = self.selectionModel().selectedIndexes()
            if indexes:
                index = self.model().index(indexes[0].row() - 1, indexes[0].column())
            else:
                index = self.model().index(self.model().rowCount()-1, 0)
            self.selectionModel().select(index, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
    

    Thoughts on where to start here?

    Thanks!

    https://alaskafamilysystems.com/

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

      Hi,

      I'd start by a boundary check. You allow your index to go over the last element and prior to the first element in your model.

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

      P 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

        I'd start by a boundary check. You allow your index to go over the last element and prior to the first element in your model.

        P Offline
        P Offline
        patrickkidd
        wrote on last edited by
        #3

        @SGaist I am having trouble following. Would you mind rephrasing your reply? Thank you!

        https://alaskafamilysystems.com/

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

          You don't check wether your rows calculation stay between zero and model' row count - 1.

          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
          • P Offline
            P Offline
            patrickkidd
            wrote on last edited by
            #5

            That is correct. Although the problem I am having is in the middle of the range of rows.

            https://alaskafamilysystems.com/

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

              I don't remember whether the selected indexes are ordered, did you check that ?

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

              P 2 Replies Last reply
              0
              • SGaistS SGaist

                I don't remember whether the selected indexes are ordered, did you check that ?

                P Offline
                P Offline
                patrickkidd
                wrote on last edited by
                #7

                @SGaist the table view is set to only select a single, entire row at a time. So that shouldn’t matter.

                https://alaskafamilysystems.com/

                1 Reply Last reply
                0
                • SGaistS SGaist

                  I don't remember whether the selected indexes are ordered, did you check that ?

                  P Offline
                  P Offline
                  patrickkidd
                  wrote on last edited by
                  #8

                  @SGaist what is very curious is that it only skips rows that have the same value in the sort column, and only when going from a high value to a low value. That tells me that it could have something to do with my model code. But I am not sure what to check there.

                  https://alaskafamilysystems.com/

                  P 1 Reply Last reply
                  0
                  • P patrickkidd

                    @SGaist what is very curious is that it only skips rows that have the same value in the sort column, and only when going from a high value to a low value. That tells me that it could have something to do with my model code. But I am not sure what to check there.

                    P Offline
                    P Offline
                    patrickkidd
                    wrote on last edited by
                    #9

                    @patrickkidd Here is my model code:

                    class EventModel(QAbstractTableModel, util.Debug):
                    
                        DATE = 'Date'
                        DESCRIPTION = 'Description'
                        PERSON = 'Person'
                        LOGGED = 'Logged'
                        SYMPTOM = 'Δ Symptom'
                        ANXIETY = 'Anxiety'
                        RELATIONSHIP = 'Relationship'
                        FUNCTIONING = 'Functioning'
                    
                        HEADERS = [DATE, DESCRIPTION, PERSON, LOGGED,
                                   SYMPTOM, ANXIETY, RELATIONSHIP, FUNCTIONING]
                    
                        def __init__(self, parent=None):
                            super().__init__(parent)
                            self.source = None
                            self.events = []
                    
                        def init(self, source):
                            self.beginResetModel()
                            self.source = source
                            self.source.eventAdded.connect(self.onEventAdded)
                            self.source.eventChanged.connect(self.onEventChanged)
                            self.source.eventRemoved.connect(self.onEventRemoved)
                            self.events = self.source.events()
                            self.endResetModel()
                    
                        def deinit(self):
                            self.beginResetModel()
                            self.source.eventAdded.disconnect(self.onEventAdded)
                            self.source.eventChanged.disconnect(self.onEventChanged)
                            self.source.eventRemoved.disconnect(self.onEventRemoved)
                            self.source = None
                            self.events = []
                            self.endResetModel()
                    
                        def index(self, row, col, parent=QModelIndex()):
                            if self.hasIndex(row, col, parent):
                                return self.createIndex(row, col)
                            else:
                                return QModelIndex()
                    
                        def rowCount(self, index=QModelIndex()):
                            return len(self.events)
                    
                        def columnCount(self, index=QModelIndex()):
                            return len(self.HEADERS)
                    
                        def headerData(self, section, orientation, role=Qt.DisplayRole):
                            if orientation == Qt.Horizontal:
                                if role == Qt.DisplayRole:
                                    return self.HEADERS[section]
                            return QVariant()
                    
                        def isColumn(self, index, labels):
                            if not isinstance(labels, list):
                                labels = [labels]
                            for label in labels:
                                if self.HEADERS[index.column()] == label:
                                    return True
                            return False
                    
                        def data(self, index, role):
                            if role in [Qt.DisplayRole, Qt.EditRole]:
                                event = self.events[index.row()]
                                if self.isColumn(index, self.PERSON):
                                    return event.parentName()
                                elif self.isColumn(index, self.DATE):
                                    return util.dateString(event.date())
                                elif self.isColumn(index, self.DESCRIPTION):
                                    return event.description()
                                elif self.isColumn(index, self.LOGGED):
                                    return util.dateString(event.loggedDate())
                                elif self.isColumn(index, self.SYMPTOM):
                                    return event.symptom()
                                elif self.isColumn(index, self.ANXIETY):
                                    return event.anxiety()
                                elif self.isColumn(index, self.FUNCTIONING):
                                    return event.functioning()
                                elif self.isColumn(index, self.RELATIONSHIP):
                                    return event.relationship()
                            elif role == Qt.BackgroundRole:
                                event = self.events[index.row()]
                                if event.nodal():
                                    return QBrush(util.NODAL_COLOR)
                            elif role == Qt.UserRole:
                                if self.isColumn(index, self.DATE):
                                    event = self.events[index.row()]
                                    return event.date()
                                elif self.isColumn(index, self.PERSON):
                                    event = self.events[index.row()]
                                    if event.parent().__class__.__name__ != 'Scene':
                                        return event.parent().id
                                    else:
                                        return None
                            return QVariant()
                    
                        def setData(self, index, value, role=Qt.EditRole):
                            if role == Qt.EditRole:
                                event = self.events[index.row()]
                                if self.isColumn(index, self.PERSON):
                                    person = self.source.find(id=value)
                                    event.setParent(person)
                                elif self.isColumn(index, self.DATE):
                                    event.setDate(value)
                                elif self.isColumn(index, self.DESCRIPTION):
                                    event.setDescription(value)
                                elif self.isColumn(index, self.SYMPTOM):
                                    event.setSymptom(value)
                                elif self.isColumn(index, self.ANXIETY):
                                    event.setAnxiety(value)
                                elif self.isColumn(index, self.FUNCTIONING):
                                    event.setFunctioning(value)
                                elif self.isColumn(index, self.RELATIONSHIP):
                                    event.setRelationship(value)
                                else:
                                    return False
                            else:
                                return False
                            self.dataChanged.emit(index, index)
                            return True
                    
                        def flags(self, index):
                            event = self.events[index.row()]
                            if event.readOnly():
                                if (self.source.__class__.__name__ == 'Scene' and event == self.source.nowEvent) or \
                                   self.isColumn(index, [self.DESCRIPTION, self.PERSON, self.LOGGED]):
                                    return super().flags(index)
                                else:
                                    return super().flags(index) | Qt.ItemIsEditable
                            else:
                                if self.isColumn(index, [self.DATE,
                                                         self.DESCRIPTION,
                                                         self.PERSON,
                                                         self.SYMPTOM,
                                                         self.ANXIETY,
                                                         self.FUNCTIONING,
                                                         self.RELATIONSHIP]):
                                    return super().flags(index) | Qt.ItemIsEditable
                                else:
                                    return super().flags(index)                
                            return super().flags(index)
                    
                        def sort(self, column, order=Qt.AscendingOrder):
                            self.layoutAboutToBeChanged.emit()
                            self.events = sorted(self.events)
                            self.layoutChanged.emit()
                    
                        def eventForIndex(self, index):
                            return self.events[index.row()]
                    
                        def indexForEvent(self, event):
                            row = self.events.index(event)
                            return self.createIndex(row, 0)
                    
                        def eventForRow(self, row):
                            return self.events[row]
                    
                        def onEventAdded(self, event):
                            if event in self.events: # bug in Scene
                                return
                            row = self.source.events().index(event)
                            self.beginInsertRows(QModelIndex(), row, row)
                            self.events.insert(row, event)
                            self.endInsertRows()
                    
                        def onEventRemoved(self, event):
                            if not event in self.events: # bug in Scene
                                return
                            row = self.events.index(event)
                            self.beginRemoveRows(QModelIndex(), row, row)
                            self.events.remove(event)
                            self.endRemoveRows()
                    
                        def onEventChanged(self, event, property):
                            row = self.events.index(event)
                            col = None
                            if property.name() == 'date':
                                col = self.HEADERS.index(self.DATE)
                                self.sort(col)
                            elif property.name() == 'description':
                                col = self.HEADERS.index(self.DESCRIPTION)
                            elif property.name() == 'parentName':
                                col = self.HEADERS.index(self.PERSON)
                            elif property.name() == 'symptom':
                                col = self.HEADERS.index(self.SYMPTOM)
                            elif property.name() == 'anxiety':
                                col = self.HEADERS.index(self.ANXIETY)
                            elif property.name() == 'functioning':
                                col = self.HEADERS.index(self.FUNCTIONING)
                            elif property.name() == 'relationship':
                                col = self.HEADERS.index(self.RELATIONSHIP)
                            if col is not None:
                                self.dataChanged.emit(self.index(row, col),
                                                      self.index(row, col))
                    
                        def addEvent(self, after=None):
                            """ This won't get saved until it's assigned a parent """
                            event = objects.Event(self.source)
                            row = 0
                            if after:
                                row = self.indexForEvent(after).row() + 1
                            self.beginInsertRows(QModelIndex(), row, row)
                            self.events.insert(row, event)
                            self.endInsertRows()
                    

                    https://alaskafamilysystems.com/

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

                      Are you also using a custom view ?

                      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

                      • Login

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