def parent(self, index): if not index.isValid(): return QModelIndex() child_item = index.internalPointer() parent_item = get_obj_value(child_item, '_parent') if parent_item is None: return QModelIndex() grand_item = get_obj_value(parent_item, '_parent') if grand_item is None: return QModelIndex() parent_list = get_obj_value(grand_item, 'children') return self.createIndex(parent_list.index(parent_item), 0, parent_item)
def rowCount(self, parent_index=None): if parent_index and parent_index.isValid(): parent_item = parent_index.internalPointer() else: parent_item = self.root_item children_obj = get_obj_value(parent_item, 'children') return len(children_obj) if not hasattr(children_obj, 'next') else 0
def mouse_move_event(self, event): index = self.indexAt(event.pos()) real_index = utils.real_index(index) if self.header_list[real_index.column()].get('is_link', False): key_name = self.header_list[real_index.column()]['attr'] data_obj = utils.real_model(self.model()).data_list[real_index.row()] value = utils.get_obj_value(data_obj, key_name) if value: self.setCursor(Qt.PointingHandCursor) return self.setCursor(Qt.ArrowCursor)
def hasChildren(self, parent_index=None): if parent_index and parent_index.isValid(): parent_data = parent_index.internalPointer() else: parent_data = self.root_item children_obj = get_obj_value(parent_data, 'children') if children_obj is None: return False if hasattr(children_obj, 'next'): return True else: return len(children_obj)
def setData(self, index, value, role=Qt.EditRole): if index.isValid() and role in [Qt.CheckStateRole, Qt.EditRole]: attr_dict = self.header_list[index.column()] key = attr_dict.get('key') data_obj = index.internalPointer() if role == Qt.CheckStateRole and attr_dict.get('checkable', False): key += '_checked' # 更新自己 set_obj_value(data_obj, key, value) self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), index, index) # 更新它的children for row, sub_obj in enumerate(get_obj_value(data_obj, 'children', [])): set_obj_value(sub_obj, key, value) sub_index = index.child(row, index.column()) self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), sub_index, sub_index) # 更新它的parent parent_index = index.parent() if parent_index.isValid(): parent_obj = parent_index.internalPointer() new_parent_value = value old_parent_value = get_obj_value(parent_obj, key) for sibling_obj in get_obj_value(get_obj_value(data_obj, '_parent'), 'children', []): if value != get_obj_value(sibling_obj, key): new_parent_value = 1 break if new_parent_value != old_parent_value: set_obj_value(parent_obj, key, new_parent_value) self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), parent_index, parent_index) else: set_obj_value(data_obj, key, value) # 采用 self.dataChanged.emit方式在houdini16里面会报错 # TypeError: dataChanged(QModelIndex,QModelIndex,QVector<int>) only accepts 3 arguments, 3 given! # 所以临时使用旧式信号的发射方式 self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), index, index) # self.dataChanged.emit(index, index) return True else: return False
def createEditor(self, parent, option, index): self.parent_widget = parent self.editor = MMenu(exclusive=self.exclusive, parent=parent) self.editor.setWindowFlags(Qt.FramelessWindowHint | Qt.Window) model = utils.real_model(index) real_index = utils.real_index(index) data_obj = real_index.internalPointer() attr = '{}_list'.format( model.header_list[real_index.column()].get('key')) self.editor.set_data(utils.get_obj_value(data_obj, attr, [])) self.editor.sig_value_changed.connect(self._slot_finish_edit) return self.editor
def index(self, row, column, parent_index=None): if parent_index and parent_index.isValid(): parent_item = parent_index.internalPointer() else: parent_item = self.root_item children_list = get_obj_value(parent_item, 'children') if children_list and len(children_list) > row: child_item = children_list[row] if child_item: set_obj_value(child_item, '_parent', parent_item) return self.createIndex(row, column, child_item) return QModelIndex()
def data(self, index, role=Qt.DisplayRole): if not index.isValid(): return None attr_dict = self.header_list[index.column()] # 获取该列字段的配置 data_obj = index.internalPointer() attr = attr_dict.get('key') if role in SETTING_MAP.keys(): role_key = SETTING_MAP[role].get('config') # role 配置的关键字 formatter_from_config = attr_dict.get(role_key) # header中该role的配置 if not formatter_from_config and role not in [Qt.DisplayRole, Qt.EditRole, Qt.ToolTipRole]: # 如果header中没有配置该role,而且也不是 DisplayRole/EditRole,直接返回None return None else: value = apply_formatter(formatter_from_config, get_obj_value(data_obj, attr), data_obj) formatter_from_model = SETTING_MAP[role].get('formatter', None) # role 配置的转换函数 result = apply_formatter(formatter_from_model, value) return result if role == Qt.CheckStateRole and attr_dict.get('checkable', False): state = get_obj_value(data_obj, attr + '_checked') return Qt.Unchecked if state is None else state return None
def _slot_set_select(self, column, state): current_model = self.model() source_model = utils.real_model(current_model) source_model.beginResetModel() attr = '{}_checked'.format(source_model.header_list[column].get('key')) for row in range(current_model.rowCount()): real_index = utils.real_index(current_model.index(row, column)) data_obj = real_index.internalPointer() if state is None: old_state = utils.get_obj_value(data_obj, attr) utils.set_obj_value( data_obj, attr, Qt.Unchecked if old_state == Qt.Checked else Qt.Checked) else: utils.set_obj_value(data_obj, attr, state) source_model.endResetModel() source_model.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), None, None)
def mouse_release_event(self, event): if event.button() != Qt.LeftButton: QTableView.mouseReleaseEvent(self, event) return index = self.indexAt(event.pos()) real_index = utils.real_index(index) if self.headerList[real_index.column()].get('is_link', False): key_name = self.header_list[real_index.column()]['attr'] data_obj = utils.real_model(self.model()).data_list[real_index.row()] value = utils.get_obj_value(data_obj, key_name) if value: if isinstance(value, dict): self.sig_link_clicked.emit(value) elif isinstance(value, basestring): self.sig_link_clicked.emit(data_obj) elif isinstance(value, list): for i in value: self.sig_link_clicked.emit(i)
def test_set_obj_value(self, obj, attr, value): """Test set_obj_value with dict/object as arg. """ utils.set_obj_value(obj, attr, value) assert utils.get_obj_value(obj, attr) == value
def test_get_obj_value(self, obj, attr, default, result): """Test get_obj_value with dict/object as arg. """ assert utils.get_obj_value(obj, attr, default) == result