def parent(self, index): if not index.isValid(): return QtCore.QModelIndex() node = index.internalPointer() parent = node.parent() if parent is None: return QtCore.QModelIndex() else: return self.createIndex(parent.row, 0, parent)
def _lastIndex(self): """Index of the very last item in the tree. """ currentIndex = QtCore.QModelIndex() rowCount = self.rowCount(currentIndex) while rowCount > 0: currentIndex = self.index(rowCount - 1, 0, currentIndex) rowCount = self.rowCount(currentIndex) return currentIndex
def findIndex(self, rowPath): """Returns the QtCore.QModelIndex at `rowPath` `rowPath` is a sequence of node rows. For example, [1, 2, 1] is the 2nd child of the 3rd child of the 2nd child of the root. """ result = QtCore.QModelIndex() for row in rowPath: result = self.index(row, 0, result) return result
def refresh(self): updated = set() to_add = set() object_ids = set() rows = self._index columnCount = self.columnCount() parent = QtCore.QModelIndex() objects = self.fetchObjects() # Update existing for obj in objects: object_ids.add(obj.id) try: idx = self._index[obj.id] self._items[idx] = obj updated.add(obj.id) self.dataChanged.emit(self.index(idx, 0), self.index(idx, columnCount - 1)) except (IndexError, KeyError): to_add.add(obj) # Add new if to_add: size = len(to_add) start = len(self._items) end = start + size - 1 self.beginInsertRows(parent, start, end) self._items.extend(to_add) self.endInsertRows() LOGGER.debug("adding %d new objects", size) # Remove missing if self.refreshShouldRemove: to_remove = set(self._index.iterkeys()).difference(object_ids) if to_remove: row_ids = ((rows[old_id], old_id) for old_id in to_remove) for row, old_id in sorted(row_ids, reverse=True): self.beginRemoveRows(parent, row, row) obj = self._items.pop(row) self.endRemoveRows() LOGGER.debug("removing %s %s", old_id, obj.name) # reindex the items self._index = dict( ((item.id, i) for i, item in enumerate(self._items)))
def refreshData(self): """Updates the data on all nodes, but without having to perform a full reset. A full reset on a tree makes us lose selection and expansion states. When all we ant to do is to refresh the data on the nodes without adding or removing a node, a call on dataChanged() is better. But of course, Qt makes our life complicated by asking us topLeft and bottomRight indexes. This is a convenience method refreshing the whole tree. """ columnCount = self.columnCount() topLeft = self.index(0, 0, QtCore.QModelIndex()) bottomLeft = self._lastIndex() bottomRight = self.sibling(bottomLeft.row(), columnCount - 1, bottomLeft) self.dataChanged.emit(topLeft, bottomRight)
def index(self, row, column, parent): if not self.subnodes: return QtCore.QModelIndex() node = parent.internalPointer() if parent.isValid() else self try: return self.createIndex(row, column, node.subnodes[row]) except IndexError: logging.debug( "Wrong tree index called (%r, %r, %r). Returning DummyNode", row, column, node) parentNode = parent.internalPointer() if parent.isValid() else None dummy = self._createDummyNode(parentNode, row) self._dummyNodes.add(dummy) return self.createIndex(row, column, dummy)
def refresh(self): if not self.__items: self.reload() return rows = self.__index colCount = self.columnCount() parent = QtCore.QModelIndex() nodes = plow.client.get_nodes() nodes_ids = set() to_add = set() # Update for node in nodes: nodes_ids.add(node.id) if node.id in self.__index: row = rows[node.id] self.__items[row] = node start = self.index(row, 0) end = self.index(row, colCount - 1) self.dataChanged.emit(start, end) LOGGER.debug("updating %s %s", node.id, node.name) else: to_add.add(node) # Add new if to_add: size = len(to_add) start = len(self.__items) end = start + size - 1 self.beginInsertRows(parent, start, end) self.__items.extend(to_add) self.endInsertRows() LOGGER.debug("adding %d new nodes", size) # Remove to_remove = set(self.__index.iterkeys()).difference(nodes_ids) for row, old_id in sorted( ((rows[old_id], old_id) for old_id in to_remove), reverse=True): self.beginRemoveRows(parent, row, row) node = self.__items.pop(row) self.endRemoveRows() LOGGER.debug("removing %s %s", old_id, node.name) self.__index = dict((n.id, row) for row, n in enumerate(self.__items))
def refresh(self): projects = self.__attrs.get('projects', []) if not projects: self.reset() return if not self.__folders: self.reload() return rows = self.__folder_index colCount = self.columnCount() parent = QtCore.QModelIndex() folder_ids = set() to_add = set() folderNodes = dict((f.ref.id, f) for f in self.subnodes) # pull the job board folders = chain.from_iterable(imap(plow.client.get_job_board, projects)) # Update for folder in folders: folder_ids.add(folder.id) row = rows.get(folder.id) if row is None: to_add.add(folder) else: oldFolder = self.__folders[row] folderNode = folderNodes[folder.id] self.__updateJobs(folderNode, folder) folderNode.ref = folder self.__folders[row] = folder start = self.index(row, 0) end = self.index(row, colCount-1) self.dataChanged.emit(start, end) LOGGER.debug("updating %s %s", folder.id, folder.name) # Add new if to_add: size = len(to_add) start = len(self.__folders) end = start + size - 1 self.beginInsertRows(parent, start, end) self.__folders.extend(to_add) self.invalidate() self.endInsertRows() LOGGER.debug("adding %d new folders", size) # Remove to_remove = ((rows[f_id], f_id) for f_id in set(rows).difference(folder_ids)) for row, f_id in sorted(to_remove, reverse=True): self.beginRemoveRows(parent, row, row) folder = self.__folders.pop(row) self.subnodes.remove(folderNodes[f_id]) self.endRemoveRows() LOGGER.debug("removing %s %s", f_id, folder.name) # re-index the rows self.__folder_index = dict((f.id, row) for row, f in enumerate(self.__folders))
def columnCount(self, parent=QtCore.QModelIndex()): return len(JobNode.HEADERS)
def index(self, row, column, parent=QtCore.QModelIndex()): return super(JobModel, self).index(row, column, parent)
def rowCount(self, parent=QtCore.QModelIndex()): node = parent.internalPointer() if parent.isValid() else self return len(node.subnodes)