def add_option_handler(self): selection = self.view.selectionModel().selectedRows() if len(selection) == 0 or len(selection) > 1: logging.debug( "zero or multiple selections while trying to add new value") self.statusbar.showMessage( "Please select one option to add new value") return selected_index = get_root_index(selection[0]) option = selected_index.data() parent = QtCore.QModelIndex() for r in range(self.json_model.rowCount(parent)): index = self.json_model.index(r, 0, parent) item = self.json_model.itemFromIndex(index) if index.data() == option: if option in mss_default.fixed_dict_options + mss_default.key_value_options: # Cannot add options to fixed structure options self.statusbar.showMessage( "Option already exists. Please change value to your preference or restore to default." ) return elif option in mss_default.dict_option_structure: # Append dummy value dict to options having a dictionary structure json_data = mss_default.dict_option_structure[option] type_ = match_type(json_data) type_.next(model=self.json_model, data=json_data, parent=item) elif option in mss_default.list_option_structure: # Append dummy value to options having a list structure json_data = mss_default.list_option_structure[option] type_ = match_type(json_data) type_.next(model=self.json_model, data=json_data, parent=item) # increase row count in view rows = self.json_model.rowCount(index) - 1 new_item = self.json_model.itemFromIndex( self.json_model.index(rows, 0, index)) new_item.setData(rows, QtCore.Qt.DisplayRole) self.statusbar.showMessage("") # expand root item proxy_index = self.proxy_model.mapFromSource(index) self.view.expand(proxy_index) # expand, scroll to and select new item rows = self.json_model.rowCount(index) - 1 new_index = self.json_model.index(rows, 0, index) proxy_index = self.proxy_model.mapFromSource(new_index) self.view.expand(proxy_index) self.view.scrollTo(proxy_index) self.view.selectionModel().select( proxy_index, QtCore.QItemSelectionModel.ClearAndSelect | QtCore.QItemSelectionModel.Rows) logging.debug(f"Added new value for {option}") self.update_view() break
def compare_data(default, user_data): """ Recursively compares two dictionaries based on qt_json_view datatypes and returns default or user_data appropriately. Arguments: default -- Dict to return if datatype not matching user_data -- Dict to return if datatype is matching """ # If data is neither list not dict type, compare individual type if not isinstance(default, dict) and not isinstance(default, list): if isinstance(default, float) and isinstance(user_data, int): user_data = float(default) if isinstance(match_type(default), UrlType) and isinstance( match_type(user_data), StrType): return user_data, True if isinstance(match_type(default), type(match_type(user_data))): return user_data, True else: return default, False data = copy.deepcopy(default) matches = [] # If data is list type, compare all values in list if isinstance(default, list) and isinstance(user_data, list): if len(default) == len(user_data): for i in range(len(default)): data[i], match = compare_data(default[i], user_data[i]) matches.append(match) else: return default, False # If data is dict type, goes through the dict and update elif isinstance(default, dict) and isinstance(user_data, dict): if default.keys() == user_data.keys(): for key in default: if key in user_data: data[key], match = compare_data(default[key], user_data[key]) matches.append(match) else: matches.append(False) else: return default, False return data, all(matches)
def init(self, data, editable_keys=False, editable_values=False): """Convert the data to items and populate the model.""" self.clear() self.setHorizontalHeaderLabels(['Key', 'Value']) self.editable_keys = editable_keys self.editable_values = editable_values parent = self.invisibleRootItem() type_ = match_type(data) parent.setData(type_, TypeRole) type_.next(model=self, data=data, parent=parent)
def restore_defaults(self): def update(data, option, value): """Function to update dict at a depth""" for k, v in data.items(): if k == option: data[k] = value break if isinstance(v, collections.abc.Mapping): data[k] = update(data.get(k, {}), option, value) return data selection = self.view.selectionModel().selectedRows() if len(selection) == 0: logging.debug("no selections while trying to restore defaults") self.statusbar.showMessage( "Please select one/more options to restore defaults") return # get list of distinct indexes to restore model_data = self.json_model.serialize() selected_indexes = set() for index in selection: root_index, parent_list = get_root_index(index, parents=True) added = False data = model_data for parent in parent_list + [index]: data = data[parent.data()] if isinstance(data, list): added = True selected_indexes.add(parent) break if not added: selected_indexes.add(index) # ToDo add confirmation dialog here options = "\n".join([index.data() for index in selected_indexes]) logging.debug( f"Attempting to restore defaults for the following options\n{options}" ) for index in selected_indexes: # check if root option and present in mss_default.key_value_options if not index.parent().isValid() and index.data( ) in mss_default.key_value_options: value_index = self.json_model.index(index.row(), 1, QtCore.QModelIndex()) value_item = self.json_model.itemFromIndex(value_index) value_item.setData(default_options[index.data()], QtCore.Qt.DisplayRole) continue root_index, parent_list = get_root_index(index, parents=True) option = root_index.data() model_data = self.json_model.serialize() if option in mss_default.fixed_dict_options: if index == root_index: json_data = default_options[option] else: key = None value = copy.deepcopy(default_options) for parent in parent_list + [index]: parent_data = parent.data() if isinstance(value, list): break key = parent_data value = value[parent_data] data = copy.deepcopy(model_data[option]) json_data = update(data, key, value) else: json_data = default_options[option] if model_data[option] == json_data: continue # remove all rows for row in range(self.proxy_model.rowCount(root_index)): self.proxy_model.removeRow(0, parent=root_index) # add default values source_index = self.proxy_model.mapToSource(root_index) source_item = self.json_model.itemFromIndex(source_index) type_ = match_type(json_data) type_.next(model=self.json_model, data=json_data, parent=source_item) self.statusbar.showMessage("Defaults restored for selected options") self.view.clearSelection() self.update_view()