def _propagateSelectionUp(self, selection, command): """ """ parentSelection = QtGui.QItemSelection() # filter out duplicates by unique id because pyside QModelIndexes are not hashable, and cannot be added to a set parentIndexes = map(QtCore.QModelIndex.parent, selection.indexes()) parentIndexes = dict( zip(map(self.model().uniqueIdFromIndex, parentIndexes), parentIndexes)).values() for index in parentIndexes: while index.isValid(): if not (selection.contains(index) or parentSelection.contains(index)): if command & QtGui.QItemSelectionModel.Deselect: # children are being deselected, deselect parents too parentSelection.select(index, index) elif command & QtGui.QItemSelectionModel.Select: # children are being selected, select parent if all children are now selected numChildren = self.model().rowCount(index) if numChildren: numSelected = 0 for row in xrange(numChildren): childIndex = self.model().index(row, 0, index) if selection.contains(childIndex) or \ parentSelection.contains(childIndex) or \ (not (command & QtGui.QItemSelectionModel.Clear) and self.isSelected( childIndex)): numSelected += 1 else: break if numSelected == numChildren: # all children are selected, select parent too parentSelection.select(index, index) index = index.parent() return parentSelection
def selectAll(self): """ """ if not isinstance(self.selectionModel(), TreeSelectionModel): return QtGui.QTreeView.selectAll(self) # store parameters selectionModel = self.selectionModel() model = self.model() getIndex = model.index columnCount = model.columnCount(QtCore.QModelIndex()) selection = QtGui.QItemSelection() propagate = selectionModel.propagateSelection() oldSelection = selectionModel.selection() def selectChildRange(parentIndex): rowCount = model.rowCount(parentIndex) firstIndex = getIndex(0, 0, parentIndex) lastIndex = getIndex(rowCount - 1, columnCount - 1, parentIndex) selection.select(firstIndex, lastIndex) def recursiveSelect(parentIndex): selectChildRange(parentIndex) if propagate is True: # if we skip this check it will always select child rows. for row in range(model.rowCount(parentIndex)): index = getIndex(row, 0, parentIndex) if index.isValid(): recursiveSelect(index) # prepare block = selectionModel.blockSignals(True) self.setUpdatesEnabled(False) if propagate is True: selectionModel.setPropagateSelection(False) # do selection if self.selectionMode() == QtGui.QAbstractItemView.SingleSelection: selection.select( model.index(0, 0, QtCore.QModelIndex()), model.index(0, columnCount - 1, QtCore.QModelIndex())) else: recursiveSelect(QtCore.QModelIndex()) selectionModel.select(selection, QtGui.QItemSelectionModel.Select) # restore previous settings self.setUpdatesEnabled(True) selectionModel.setPropagateSelection(propagate) selectionModel.blockSignals(block) # refresh view QtGui.QApplication.processEvents() selectionModel.selectionChanged.emit(selection, oldSelection)
def __propagateSelectionDown(self, selection): """ """ childSelection = QtGui.QItemSelection() indexQueue = selection.indexes() while indexQueue: index = indexQueue.pop(0) if index.isValid(): numChildren = self.model().rowCount(index) childIndexes = [ self.model().index(row, 0, index) for row in xrange(numChildren) ] if childIndexes: # add child indexes to the selection childSelection.append( QtGui.QItemSelectionRange(childIndexes[0], childIndexes[-1])) indexQueue.extend(childIndexes) return childSelection
def select(self, selection, command): """ Select items :parameters: selection : QtGui.QItemSelection selected model items command : QtGui.QItemSelectionModel.SelectionFlags NoUpdate: No selection will be made. Clear: The complete selection will be cleared. Select: All specified indexes will be selected. Deselect: All specified indexes will be deselected. Toggle: All specified indexes will be selected or deselected depending on their current state. Current: The current selection will be updated. Rows: All indexes will be expanded to span rows. Columns: All indexes will be expanded to span columns. SelectCurrent:A combination of Select and Current, provided for convenience. ToggleCurrent: A combination of Toggle and Current, provided for convenience. ClearAndSelect: A combination of Clear and Select, provided for convenience. """ if self.__propagateSelection: # propagate selection to children/parents of selected indexes if isinstance(selection, QtCore.QModelIndex): selection = QtGui.QItemSelection(selection, selection) # propagate selection down to children childSelection = self.__propagateSelectionDown(selection) # propagate selection up to parents parentSelection = self._propagateSelectionUp(selection, command) selection.merge(childSelection, QtGui.QItemSelectionModel.SelectCurrent) selection.merge(parentSelection, QtGui.QItemSelectionModel.SelectCurrent) # NOTE: the 'command' parameter is really the 'selectionFlags' self.__lastselectionflags = command if (command & QtGui.QItemSelectionModel.Columns): # NOTE: I'm not sure anyone ever has this set but just in # case for compatibility. In future we should apptrack # this and if no one uses column seleciton then this # option should be removed. previousSelection = self.selectedIndexes() else: # This saves on many many duplicates in the selection previousSelection = self.selectedRows() QtGui.QItemSelectionModel.select(self, selection, command) # NOTE: the 'command' parameter is really 'selectionFlags' if (command & QtGui.QItemSelectionModel.Columns): # NOTE: I'm not sure anyone ever has this set but just in # case for compatibility. In future we should apptrack # this and if no one uses column seleciton then this # option should be removed. selected_now = self.selectedIndexes() else: # This saves on many many duplicates in the selection selected_now = self.selectedRows() self.setSelectionStates(selected_now, previous=previousSelection) self.requestRefresh()