def _map_variable_to_definition_node(self, variable_node): ''' creates a mapping between the variables (name, dataset) and it's definition node ''' dataset, name = get_variable_dataset_and_name(variable_node) expression_lib_nodes = get_variable_nodes_per_dataset(self.project) # Before XML 2.0 there was no dataset associated with variable selections, so some converted # files might have an empty dataset (variable name starts with a . [dot]). # in these cases we try to guess wich variable in the expression lib to associate with. # Note that built-ins like 'constant' return None as dataset, not an empty string. if dataset == '': possible_datasets = [] for dataset_name, variable_nodes in expression_lib_nodes.items(): for variable_definition_node in variable_nodes: def_variable_name = get_variable_name( variable_definition_node) if def_variable_name == name: possible_datasets.append(dataset_name) break if len(possible_datasets) == 1: dataset = possible_datasets[0] # update the variable node with the guessed dataset # variable_node.set('name', '%s.%s' %(dataset, name)) if not dataset in expression_lib_nodes: self._names_to_definition_nodes[(name, dataset)] = None else: # look through the dataset to find a variable with the same name for variable_definition_node in expression_lib_nodes[dataset]: def_variable_name = get_variable_name(variable_definition_node) if def_variable_name == name: self._names_to_definition_nodes[( name, dataset)] = variable_definition_node break else: self._names_to_definition_nodes[(name, dataset)] = None
def _update_available_variables(self): # populate the list of available variables while considering A) what dataset filter the user # has selected, an d B) what variables that have already been selected) self.lst_available_variables.clear() if self.cbo_dataset_filter.currentIndex() > 0: dataset_filter = str(self.cbo_dataset_filter.currentText()) else: dataset_filter = None selected_variable_names = [node.get('name') for node in self.selector_table_model._variable_nodes] available_variable_nodes = [] variable_nodes_per_dataset = get_variable_nodes_per_dataset(self.project) if not dataset_filter: # take all variables for variable_nodes in variable_nodes_per_dataset.values(): available_variable_nodes.extend(variable_nodes) else: available_variable_nodes = variable_nodes_per_dataset[dataset_filter] available_variable_nodes.append(get_built_in_constant_node()) # filter already selected variables and show the list of available variables not_selected_variables = [var_node for var_node in available_variable_nodes if not var_node.get('name') in selected_variable_names] for variable_node in not_selected_variables: item = QtGui.QListWidgetItem(self.lst_available_variables) item.setIcon(IconLibrary.icon('variable')) item.node = variable_node # monkey in the node for adding later item.setText(get_variable_name(variable_node)) self.lst_available_variables.addItem(item) self.lst_available_variables.sortItems()
def _create_add_variable_menu(self): # function to display variables in the popup menu def display_node(node, selected_nodes): if node in selected_nodes: return '(already selected) %s' % get_variable_name(node) return get_variable_name(node) # call back to only add unselected variables from the popup menu def add_if_unselected(node, selected_nodes): if not node in selected_nodes: self.add_variable(node) dataset_variable_nodes = get_variable_nodes_per_dataset(self.project) selected_names = map(get_variable_name, self.selector_table_model._variable_nodes) selected_nodes = [] for variable_node_list in dataset_variable_nodes.values(): for variable_node in variable_node_list: if get_variable_name(variable_node) in selected_names: selected_nodes.append(variable_node) # sort by variable name variable_node_list.sort(lambda x, y: cmp(get_variable_name(x), get_variable_name(y))) # display selected items at the bottom for node in variable_node_list[:]: if node in selected_nodes: variable_node_list.remove(node) variable_node_list.insert(len(variable_node_list), node) display_func = lambda x, y = selected_nodes: display_node(x, y) callback = lambda x, y = selected_nodes: add_if_unselected(x, y) return dictionary_to_menu(source_dict = dataset_variable_nodes, callback = callback, display_func = display_func, parent_widget = self)
def _map_variable_to_definition_node(self, variable_node): ''' creates a mapping between the variables (name, dataset) and it's definition node ''' dataset, name = get_variable_dataset_and_name(variable_node) expression_lib_nodes = get_variable_nodes_per_dataset(self.project) # Before XML 2.0 there was no dataset associated with variable selections, so some converted # files might have an empty dataset (variable name starts with a . [dot]). # in these cases we try to guess wich variable in the expression lib to associate with. # Note that built-ins like 'constant' return None as dataset, not an empty string. if dataset == '': possible_datasets = [] for dataset_name, variable_nodes in expression_lib_nodes.items(): for variable_definition_node in variable_nodes: def_variable_name = get_variable_name(variable_definition_node) if def_variable_name == name: possible_datasets.append(dataset_name) break if len(possible_datasets) == 1: dataset = possible_datasets[0] # update the variable node with the guessed dataset # variable_node.set('name', '%s.%s' %(dataset, name)) if not dataset in expression_lib_nodes: self._names_to_definition_nodes[(name, dataset)] = None else: # look through the dataset to find a variable with the same name for variable_definition_node in expression_lib_nodes[dataset]: def_variable_name = get_variable_name(variable_definition_node) if def_variable_name == name: self._names_to_definition_nodes[(name, dataset)] = variable_definition_node break else: self._names_to_definition_nodes[(name, dataset)] = None
def _widget_and_method_from_field_data_type(self, template_node): ''' Fetch the widget and the data-method for a given node based in it's field_data_type argument. If the node doesn't have a field_data_type, or it's value is unknown, return None ''' data_type = template_node.get('field_data_type') if not data_type: return None # Helper function to get a string based on the model name. # both the name and the type of the model node are updated before this method is called. def get_model_name_based_string(node=template_node, prefix='', suffix=''): while node is not None and node.tag != 'model': node = node.getparent() if node is None: raise LookupError( 'Could not locate the parent <model> node for %s' % str(node)) return '%s%s%s' % (prefix, node.get('name'), suffix) # dataset if data_type == 'dataset': widget = QtGui.QComboBox() for dataset_name in get_available_dataset_names(self.project): widget.addItem(dataset_name) return (widget, widget.currentText) # model variable if data_type == 'model_variable': variables_per_dataset = get_variable_nodes_per_dataset( self.project) widget = QtGui.QComboBox() for dataset, variables in variables_per_dataset.items(): for variable in variables: widget.addItem('%s: %s' % (dataset, variable.get('name'))) # return a method that only gives the name of the variable, and skips the dataset return (widget, lambda x=widget: widget.currentText().split(':')[1]) # specification table # data-method should return a table name based on the models name if data_type == 'specification_table': return (None, lambda x='_specification': get_model_name_based_string(suffix=x)) # coefficients table if data_type == 'coefficients_table': return (None, lambda x='_coefficients': get_model_name_based_string(suffix=x)) if data_type == 'choice_set': # No special handling return None # unknown, notify with a warning print( 'Warning: <%s name=%s> has a field_data_type of unknown value (%s) and is ignored.' % (template_node.tag, template_node.get('name'), data_type)) return None
def _update_dataset_filter_list(self): # update the combo box list (keeping selection) variable_nodes_per_dataset = get_variable_nodes_per_dataset(self.project) pre_update_dataset_name = self.cbo_dataset_filter.currentText() self.cbo_dataset_filter.clear() self.cbo_dataset_filter.addItem('[All datasets]') for dataset_name in variable_nodes_per_dataset: if dataset_name is not None: # built ins are manually added self.cbo_dataset_filter.addItem(dataset_name) post_update_index = self.cbo_dataset_filter.findText(pre_update_dataset_name) if post_update_index > -1: self.cbo_dataset_filter.setCurrentIndex(post_update_index)
def _update_dataset_filter_list(self): # update the combo box list (keeping selection) variable_nodes_per_dataset = get_variable_nodes_per_dataset( self.project) pre_update_dataset_name = self.cbo_dataset_filter.currentText() self.cbo_dataset_filter.clear() self.cbo_dataset_filter.addItem('[All datasets]') for dataset_name in variable_nodes_per_dataset: if dataset_name is not None: # built ins are manually added self.cbo_dataset_filter.addItem(dataset_name) post_update_index = self.cbo_dataset_filter.findText( pre_update_dataset_name) if post_update_index > -1: self.cbo_dataset_filter.setCurrentIndex(post_update_index)
def _widget_and_method_from_field_data_type(self, template_node): ''' Fetch the widget and the data-method for a given node based in it's field_data_type argument. If the node doesn't have a field_data_type, or it's value is unknown, return None ''' data_type = template_node.get('field_data_type') if not data_type: return None # Helper function to get a string based on the model name. # both the name and the type of the model node are updated before this method is called. def get_model_name_based_string(node = template_node, prefix = '', suffix = ''): while node is not None and node.tag != 'model': node = node.getparent() if node is None: raise LookupError('Could not locate the parent <model> node for %s' % str(node)) return '%s%s%s' %(prefix, node.get('name'), suffix) # dataset if data_type == 'dataset': widget = QtGui.QComboBox() for dataset_name in get_available_dataset_names(self.project): widget.addItem(dataset_name) return (widget, widget.currentText) # model variable if data_type == 'model_variable': variables_per_dataset = get_variable_nodes_per_dataset(self.project) widget = QtGui.QComboBox() for dataset, variables in variables_per_dataset.items(): for variable in variables: widget.addItem('%s: %s' % (dataset, variable.get('name'))) # return a method that only gives the name of the variable, and skips the dataset return (widget, lambda x = widget: widget.currentText().split(':')[1]) # specification table # data-method should return a table name based on the models name if data_type == 'specification_table': return (None, lambda x = '_specification' : get_model_name_based_string(suffix = x)) # coefficients table if data_type == 'coefficients_table': return (None, lambda x = '_coefficients': get_model_name_based_string(suffix = x)) if data_type == 'choice_set': # No special handling return None # unknown, notify with a warning print ('Warning: <%s name=%s> has a field_data_type of unknown value (%s) and is ignored.' % (template_node.tag, template_node.get('name'), data_type)) return None
def initialize(self): # reset the variable library to reflect the current state of expression library in xml nodes_per_dataset = get_variable_nodes_per_dataset(self.project) variables = [] all_original_nodes = set() for dataset in nodes_per_dataset: for variable_node in nodes_per_dataset[dataset]: new_variable = variable_from_node(variable_node) new_variable['originalnode'] = variable_node variables.append(new_variable) all_original_nodes.add( variable_node) # save original values for comparison self.original_nodes = all_original_nodes self.cancel_validation_flag = {'value': False} # to avoid quirky behavior when applying changes, store the column widths and restore them # after the model update col_widths = [ self.variables_table.columnWidth(col) for col in range(5) ] # bind to self to prevent PyQt from "losing" the object ref self.model = VariablesTableModel(project=self.project, variables=variables, parent_widget=self.variables_table) self.variables_table.setModel(self.model) self.model.re_sort() self.connect(self.model, SIGNAL('layoutChanged()'), self.variables_table.resizeRowsToContents) self._update_apply_button() self.group_progress.setVisible(False) self.pb_problems.setIcon(IconLibrary.icon('warning_small')) self.pb_problems.setAttribute(Qt.WA_AlwaysShowToolTips) self._set_problem_variables([]) self._update_dataset_filter() # use the inital size if the column widths is all zeroes if sum(abs(w) for w in col_widths) == 0: col_widths = [195, 80, 45, 50, -1] for col in range(5): if col_widths[col] > 0: self.variables_table.setColumnWidth(col, col_widths[col]) self.variables_table.resizeRowsToContents()
def initialize(self): # reset the variable library to reflect the current state of expression library in xml nodes_per_dataset = get_variable_nodes_per_dataset(self.project) variables = [] all_original_nodes = set() for dataset in nodes_per_dataset: for variable_node in nodes_per_dataset[dataset]: new_variable = variable_from_node(variable_node) new_variable['originalnode'] = variable_node variables.append(new_variable) all_original_nodes.add(variable_node) # save original values for comparison self.original_nodes = all_original_nodes self.cancel_validation_flag = {'value': False} # to avoid quirky behavior when applying changes, store the column widths and restore them # after the model update col_widths = [self.variables_table.columnWidth(col) for col in range(5)] # bind to self to prevent PyQt from "losing" the object ref self.model = VariablesTableModel(project = self.project, variables = variables, parent_widget = self.variables_table) self.variables_table.setModel(self.model) self.model.re_sort() self.connect(self.model, SIGNAL('layoutChanged()'), self.variables_table.resizeRowsToContents) self._update_apply_button() self.group_progress.setVisible(False) self.pb_problems.setIcon(IconLibrary.icon('warning_small')) self.pb_problems.setAttribute(Qt.WA_AlwaysShowToolTips) self._set_problem_variables([]) self._update_dataset_filter() # use the inital size if the column widths is all zeroes if sum(abs(w) for w in col_widths) == 0: col_widths = [195, 80, 45, 50, -1] for col in range(5): if col_widths[col] > 0: self.variables_table.setColumnWidth(col, col_widths[col]) self.variables_table.resizeRowsToContents()
def _update_available_variables(self): # populate the list of available variables while considering A) what dataset filter the user # has selected, an d B) what variables that have already been selected) self.lst_available_variables.clear() if self.cbo_dataset_filter.currentIndex() > 0: dataset_filter = str(self.cbo_dataset_filter.currentText()) else: dataset_filter = None selected_variable_names = [ node.get('name') for node in self.selector_table_model._variable_nodes ] available_variable_nodes = [] variable_nodes_per_dataset = get_variable_nodes_per_dataset( self.project) if not dataset_filter: # take all variables for variable_nodes in variable_nodes_per_dataset.values(): available_variable_nodes.extend(variable_nodes) else: available_variable_nodes = variable_nodes_per_dataset[ dataset_filter] available_variable_nodes.append(get_built_in_constant_node()) # filter already selected variables and show the list of available variables not_selected_variables = [ var_node for var_node in available_variable_nodes if not var_node.get('name') in selected_variable_names ] for variable_node in not_selected_variables: item = QtGui.QListWidgetItem(self.lst_available_variables) item.setIcon(IconLibrary.icon('variable')) item.node = variable_node # monkey in the node for adding later item.setText(get_variable_name(variable_node)) self.lst_available_variables.addItem(item) self.lst_available_variables.sortItems()
def _create_add_variable_menu(self): # function to display variables in the popup menu def display_node(node, selected_nodes): if node in selected_nodes: return '(already selected) %s' % get_variable_name(node) return get_variable_name(node) # call back to only add unselected variables from the popup menu def add_if_unselected(node, selected_nodes): if not node in selected_nodes: self.add_variable(node) dataset_variable_nodes = get_variable_nodes_per_dataset(self.project) selected_names = map(get_variable_name, self.selector_table_model._variable_nodes) selected_nodes = [] for variable_node_list in dataset_variable_nodes.values(): for variable_node in variable_node_list: if get_variable_name(variable_node) in selected_names: selected_nodes.append(variable_node) # sort by variable name variable_node_list.sort( lambda x, y: cmp(get_variable_name(x), get_variable_name(y))) # display selected items at the bottom for node in variable_node_list[:]: if node in selected_nodes: variable_node_list.remove(node) variable_node_list.insert(len(variable_node_list), node) display_func = lambda x, y=selected_nodes: display_node(x, y) callback = lambda x, y=selected_nodes: add_if_unselected(x, y) return dictionary_to_menu(source_dict=dataset_variable_nodes, callback=callback, display_func=display_func, parent_widget=self)