def index(self, row, column, parent): """generate an index for this item""" if self.rootItem is None: return QModelIndex() if (row < 0 or column < 0 or row >= self.rowCount(parent) or column >= self.columnCount(parent)): return QModelIndex() parentItem = self.itemForIndex(parent) assert parentItem item = parentItem.child(row) if item: return self.createIndex(row, column, item) return QModelIndex()
def refresh(self): """load this game and this player. Keep parameter list identical with ExplainView""" if not self.game: # keep scores of previous game on display return if self.scoreModel: expandGroups = [ self.viewLeft.isExpanded( self.scoreModel.index(x, 0, QModelIndex())) for x in range(4) ] else: expandGroups = [True, False, True, True] gameid = str(self.game.seed or self.game.gameid) if self.game.finished(): title = i18n('Final scores for game <numid>%1</numid>', gameid) else: title = i18n('Scores for game <numid>%1</numid>', gameid) decorateWindow(self, title) self.ruleTree.rulesets = list([self.game.ruleset]) self.scoreModel = ScoreModel(self) if Debug.modelTest: self.scoreModelTest = ModelTest(self.scoreModel, self) for view in [self.viewLeft, self.viewRight]: view.setModel(self.scoreModel) header = view.header() header.setStretchLastSection(False) view.setAlternatingRowColors(True) self.viewRight.header().setSectionResizeMode(QHeaderView.Fixed) for col in range(self.viewLeft.header().count()): self.viewLeft.header().setSectionHidden(col, col > 0) self.viewRight.header().setSectionHidden(col, col == 0) self.scoreLayout.setStretch(1, 100) self.scoreLayout.setSpacing(0) self.viewLeft.setFrameStyle(QFrame.NoFrame) self.viewRight.setFrameStyle(QFrame.NoFrame) self.viewLeft.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) for master, slave in ((self.viewRight, self.viewLeft), (self.viewLeft, self.viewRight)): master.expanded.connect(slave.expand) master.collapsed.connect(slave.collapse) master.verticalScrollBar().valueChanged.connect( slave.verticalScrollBar().setValue) for row, expand in enumerate(expandGroups): self.viewLeft.setExpanded( self.scoreModel.index(row, 0, QModelIndex()), expand) self.viewLeft.resizeColumnToContents(0) self.viewRight.setColWidth() # we need a timer since the scrollbar is not yet visible QTimer.singleShot(0, self.scrollRight)
def parent(self, index): """find the parent index""" if not index.isValid(): return QModelIndex() childItem = self.itemForIndex(index) if childItem: parentItem = childItem.parent if parentItem: if parentItem != self.rootItem: grandParentItem = parentItem.parent if grandParentItem: row = grandParentItem.children.index(parentItem) return self.createIndex(row, 0, parentItem) return QModelIndex()
def testRoleDataValues(self, role, asserter): """Tests implementation if model.data() for role. asserter is a function returning True or False""" model = self.model result = model.data(model.index(0, 0, QModelIndex()), role) if result is not None and not asserter(result): raise Exception('returned value {} is wrong')
def loadData(self): """loads all data from the data base into a 2D matrix formatted like the wanted tree""" game = self.scoreTable.game data = [] records = Query( 'select player,rotated,notrotated,penalty,won,prevailing,wind,points,payments,balance,manualrules' ' from score where game=? order by player,hand', (game.gameid, )).records humans = sorted( (x for x in game.players if not x.name.startswith('Robot'))) robots = sorted( (x for x in game.players if x.name.startswith('Robot'))) data = list( tuple([ player.localName, [HandResult(*x[1:]) for x in records if x[0] == player.nameid] ]) for player in humans + robots) self.__findMinMaxChartPoints(data) parent = QModelIndex() groupIndex = self.index(self.rootItem.childCount(), 0, parent) groupNames = [ i18nc('kajongg', 'Score'), i18nc('kajongg', 'Payments'), i18nc('kajongg', 'Balance'), i18nc('kajongg', 'Chart') ] for idx, groupName in enumerate(groupNames): self.insertRows(idx, list([ScoreGroupItem(groupName)]), groupIndex) listIndex = self.index(idx, 0, groupIndex) for idx1, item in enumerate(data): self.insertRows(idx1, list([ScorePlayerItem(item)]), listIndex)
def testRoleDataType(self, role, expectedType): """Tests implementation if model.data() for role""" model = self.model result = model.data(model.index(0, 0, QModelIndex()), role) if result is not None and not isinstance(result, expectedType): raise Exception('returned data type is {}, should be {}'.format( type(result), expectedType))
def insertRows(self, position, items, parent=QModelIndex()): """inserts items into the model""" parentItem = self.itemForIndex(parent) self.beginInsertRows(parent, position, position + len(items) - 1) for row, item in enumerate(items): parentItem.insert(position + row, item) self.endInsertRows() return True
def index(self, row, column, parent=None): """helper""" if (row < 0 or column < 0 or row >= self.rowCount(parent) or column >= self.columnCount(parent)): return QModelIndex() return self.createIndex(row, column, 0)
def appendLines(self, lines): """insert a chatline""" if not isinstance(lines, list): lines = [lines] self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount() + len(lines) - 1) self.chatLines.extend(lines) self.endInsertRows()
def hasIndex(self): """ Tests self.model's implementation of QAbstractItemModel::hasIndex() """ # Make sure that invalid values returns an invalid index assert(self.model.hasIndex(-2, -2) == False) assert(self.model.hasIndex(-2, 0) == False) assert(self.model.hasIndex(0, -2) == False) rows = self.model.rowCount(QModelIndex()) cols = self.model.columnCount(QModelIndex()) # check out of bounds assert(self.model.hasIndex(rows, cols) == False) assert(self.model.hasIndex(rows + 1, cols + 1) == False) if rows > 0: assert(self.model.hasIndex(0, 0))
def removeRows(self, position, rows=1, parent=QModelIndex()): """reimplement QAbstractItemModel.removeRows""" self.beginRemoveRows(parent, position, position + rows - 1) parentItem = self.itemForIndex(parent) for row in parentItem.children[position:position + rows]: row.remove() parentItem.children = parentItem.children[: position] + parentItem.children[ position + rows:] self.endRemoveRows() return True
def columnCount(self): """ Tests self.model's implementation of QAbstractItemModel::columnCount() and hasChildren() """ # check top row topidx = self.model.index(0, 0, QModelIndex()) assert(self.model.columnCount(topidx) >= 0) # check a column count where parent is valid childidx = self.model.index(0, 0, topidx) if childidx.isValid(): assert(self.model.columnCount(childidx) >= 0)
def data(self): """ Tests self.model's implementation of QAbstractItemModel::data() """ # Invalid index should return an invalid qvariant assert not isValid(self.model.data(QModelIndex(), Qt.DisplayRole)) if self.model.rowCount(QModelIndex()) == 0: return # A valid index should have a valid data assert isValid(self.model.index(0, 0, QModelIndex())) # shouldn't be able to set data on an invalid index assert( self.model.setData(QModelIndex(), "foo", Qt.DisplayRole) == False) # General Purpose roles that should return a QString self.testRoleDataType(Qt.ToolTipRole, str) self.testRoleDataType(Qt.StatusTipRole, str) self.testRoleDataType(Qt.WhatsThisRole, str) self.testRoleDataType(Qt.SizeHintRole, QSize) self.testRoleDataType(Qt.FontRole, QFont) self.testRoleDataType(Qt.ForegroundRole, QColor) self.testRoleDataType(Qt.BackgroundColorRole, QColor) self.testRoleDataType(Qt.TextColorRole, QColor) # Check that the alignment is one we know about self.testRoleDataValues( Qt.TextAlignmentRole, lambda x: x == (x & int(Qt.AlignHorizontal_Mask | Qt.AlignVertical_Mask))) # General Purpose roles that should return a QColor # Check that the "check state" is one we know about. self.testRoleDataValues( Qt.CheckStateRole, lambda x: x in (Qt.Unchecked, Qt.PartiallyChecked, Qt.Checked))
def appendRuleset(self, ruleset): """append ruleset to the model""" if not ruleset: return ruleset.load() parent = QModelIndex() row = self.rootItem.childCount() rulesetItems = list([RulesetItem(ruleset)]) self.insertRows(row, rulesetItems, parent) rulesetIndex = self.index(row, 0, parent) ruleLists = list(x for x in ruleset.ruleLists if len(x)) ruleListItems = list([RuleListItem(x) for x in ruleLists]) for item in ruleListItems: item.colCount = self.rootItem.columnCount() self.insertRows(0, ruleListItems, rulesetIndex) for ridx, ruleList in enumerate(ruleLists): listIndex = self.index(ridx, 0, rulesetIndex) ruleItems = list([RuleItem(x) for x in ruleList if 'internal' not in x.options]) self.insertRows(0, ruleItems, listIndex)
def rowCount(self): """ Tests self.model's implementation of QAbstractItemModel::rowCount() and hasChildren() self.models that are dynamically populated are not as fully tested here. """ # check top row topindex = self.model.index(0, 0, QModelIndex()) rows = self.model.rowCount(topindex) assert(rows >= 0) if rows > 0: assert(self.model.hasChildren(topindex)) secondlvl = self.model.index(0, 0, topindex) if secondlvl.isValid(): # check a row count where parent is valid rows = self.model.rowCount(secondlvl) assert(rows >= 0) if rows > 0: assert(self.model.hasChildren(secondlvl))
def parent(self): """ Tests self.model's implementation of QAbstractItemModel::parent() """ # Make sure the self.model wont crash and will return an invalid QModelIndex # when asked for the parent of an invalid index assert(self.model.parent(QModelIndex()) == QModelIndex()) if self.model.rowCount(QModelIndex()) == 0: return # Column 0 | Column 1 | # QtCore.Qself.modelIndex() | | # \- topidx | topidx1 | # \- childix | childidx1 | # Common error test #1, make sure that a top level index has a parent # that is an invalid QtCore.Qself.modelIndex topidx = self.model.index(0, 0, QModelIndex()) assert(self.model.parent(topidx) == QModelIndex()) # Common error test #2, make sure that a second level index has a parent # that is the first level index if self.model.rowCount(topidx) > 0: childidx = self.model.index(0, 0, topidx) assert(self.model.parent(childidx) == topidx) # 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 topidx1 = self.model.index(0, 1, QModelIndex()) if self.model.rowCount(topidx1) > 0: childidx = self.model.index(0, 0, topidx) childidx1 = self.model.index(0, 0, topidx1) assert(childidx != childidx1) # Full test, walk n levels deep through the self.model making sure that all # parent's children correctly specify their parent self.checkChildren(QModelIndex())
def index(self): """ Tests self.model's implementation of QAbstractItemModel::index() """ # Make sure that invalid values returns an invalid index assert(self.model.index(-2, -2, QModelIndex()) == QModelIndex()) assert(self.model.index(-2, 0, QModelIndex()) == QModelIndex()) assert(self.model.index(0, -2, QModelIndex()) == QModelIndex()) rows = self.model.rowCount(QModelIndex()) cols = self.model.columnCount(QModelIndex()) if rows == 0: return # Catch off by one errors assert(self.model.index(rows, cols, QModelIndex()) == QModelIndex()) assert(self.model.index(0, 0, QModelIndex()).isValid()) # Make sure that the same index is *always* returned idx1 = self.model.index(0, 0, QModelIndex()) idx2 = self.model.index(0, 0, QModelIndex()) assert(idx1 == idx2)
def nonDestructiveBasicTest(self): """ nonDestructiveBasicTest tries to call a number of the basic functions (not all) to make sure the model doesn't outright segfault, testing the functions that makes sense. """ assert(self.model.buddy(QModelIndex()) == QModelIndex()) self.model.canFetchMore(QModelIndex()) assert(self.model.columnCount(QModelIndex()) >= 0) assert(self.model.data(QModelIndex(), Qt.DisplayRole) is None) self.fetchingMore = True self.model.fetchMore(QModelIndex()) self.fetchingMore = False flags = self.model.flags(QModelIndex()) assert(int(flags & Qt.ItemIsEnabled) == Qt.ItemIsEnabled or int(flags & Qt.ItemIsEnabled) == 0) self.model.hasChildren(QModelIndex()) self.model.hasIndex(0, 0) self.model.headerData(0, Qt.Horizontal, Qt.DisplayRole) self.model.index(0, 0, QModelIndex()) self.model.itemData(QModelIndex()) cache = None self.model.match(QModelIndex(), -1, cache) self.model.mimeTypes() assert(self.model.parent(QModelIndex()) == QModelIndex()) assert(self.model.rowCount(QModelIndex()) >= 0) variant = None self.model.setData(QModelIndex(), variant, -1) self.model.setHeaderData(-1, Qt.Horizontal, None) self.model.setHeaderData(0, Qt.Horizontal, None) self.model.setHeaderData(999999, Qt.Horizontal, None) self.model.sibling(0, 0, QModelIndex()) self.model.span(QModelIndex()) self.model.supportedDropActions()
def columnCount(self, dummyIndex=QModelIndex()): # pylint: disable=no-self-use """how many columns does this node have?""" return 3 # rule name, left values, right values