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 _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 _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 _right_click_variables(self, point): ''' construct and show an operations operations_menu when the user right clicks the variable selector ''' operations_menu = QtGui.QMenu(self) add_variable_menu = self._create_add_variable_menu() add_variable_menu.setTitle('Add a variable') add_variable_menu.setIcon(IconLibrary.icon('add')) operations_menu.addMenu(add_variable_menu) index_under_cursor = self.table_selected_variables.indexAt(point) if index_under_cursor.isValid(): row = index_under_cursor.row() variable_node = self.selector_table_model.get_variable(row) self.table_selected_variables.selectRow(row) action = create_qt_action( None, 'Remove %s' % get_variable_name(variable_node), self._remove_selected_variables, self.table_selected_variables) action.setIcon(IconLibrary.icon('delete')) operations_menu.addAction(action) else: # if the index is not valid -- assume that the user clicked the "white space" of the table pass operations_menu.exec_(QtGui.QCursor.pos())
def _right_click_variables(self, point): ''' construct and show an operations operations_menu when the user right clicks the variable selector ''' operations_menu = QtGui.QMenu(self) add_variable_menu = self._create_add_variable_menu() add_variable_menu.setTitle('Add a variable') add_variable_menu.setIcon(IconLibrary.icon('add')) operations_menu.addMenu(add_variable_menu) index_under_cursor = self.table_selected_variables.indexAt(point) if index_under_cursor.isValid(): row = index_under_cursor.row() variable_node = self.selector_table_model.get_variable(row) self.table_selected_variables.selectRow(row) action = create_qt_action(None, 'Remove %s' % get_variable_name(variable_node), self._remove_selected_variables, self.table_selected_variables) action.setIcon(IconLibrary.icon('delete')) operations_menu.addAction(action) else: # if the index is not valid -- assume that the user clicked the "white space" of the table pass operations_menu.exec_(QtGui.QCursor.pos())
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 sort_variables_by_name(self): ''' sort all the variables by their variable name ''' compare_by_var_name = lambda x, y: cmp(get_variable_name(x), get_variable_name(y)) self._variable_nodes.sort(compare_by_var_name)
def data(self, index, role): if not index.isValid(): return QVariant() row = index.row() header = self._headers[index.column()] node = self._variable_nodes[row] # look up the definition once for easy access by multiple roles if header == self.HEADER_DEFINITION: dataset, name = get_variable_dataset_and_name(node) if name == 'constant': definition = '<built-in constant>' elif (name, dataset) in self._names_to_definition_nodes: definition_node = self._names_to_definition_nodes[(name, dataset)] if definition_node is not None: definition = definition_node.text else: definition = '<empty definition>' else: definition = '<unknown definition>' if role == Qt.DecorationRole: if header == self.HEADER_VARIABLE: return QVariant(IconLibrary.icon('variable')) if role == Qt.DisplayRole: var_name = get_variable_name(self._variable_nodes[row]) if header == self.HEADER_VARIABLE: return QVariant(var_name) if header == self.HEADER_DEFINITION: return QVariant(definition) if header == self.HEADER_COEFF_NAME: if 'coefficient_name' in node.attrib: return QVariant(node.get('coefficient_name')) return QVariant(var_name) if header == self.HEADER_STARTING_VAL: return QVariant(node.get('starting_value') or '') if role == Qt.EditRole: if header == self.HEADER_STARTING_VAL: return self.data(index, Qt.DisplayRole) if header == self.HEADER_COEFF_NAME: # give a clear coeff name if it's not set yet if 'coefficient_name' in node.attrib: return QVariant(node.get('coefficient_name')) return QVariant() if role == Qt.CheckStateRole: if header == self.HEADER_IGNORE: return QVariant(Qt.Checked if node.get('ignore') == 'True' else Qt.Unchecked) if header == self.HEADER_FIXED: return QVariant(Qt.Checked if node.get('keep_fixed') == 'True' else Qt.Unchecked) if role == Qt.FontRole: font = QtGui.QFont() if header == self.HEADER_VARIABLE: if node.get('ignore') != 'True': font.setBold(True) return QVariant(font) elif header == self.HEADER_COEFF_NAME and node.get( 'coefficient_name'): font.setBold(True) return QVariant(font) if role == Qt.ForegroundRole: # color default values of coefficient name as light gray if header == self.HEADER_COEFF_NAME: if 'coefficient_name' not in node.attrib: return QVariant(QtGui.QColor(Qt.gray)) if role == Qt.ToolTipRole: if header == self.HEADER_DEFINITION: # defs easily get cramped so show in tool tip as well return QVariant(definition) return QVariant()
def display_node(node, selected_nodes): if node in selected_nodes: return '(already selected) %s' % get_variable_name(node) return get_variable_name(node)
def data(self, index, role): if not index.isValid(): return QVariant() row = index.row() header = self._headers[index.column()] node = self._variable_nodes[row] # look up the definition once for easy access by multiple roles if header == self.HEADER_DEFINITION: dataset, name = get_variable_dataset_and_name(node) if name == 'constant': definition = '<built-in constant>' elif (name, dataset) in self._names_to_definition_nodes: definition_node = self._names_to_definition_nodes[(name, dataset)] if definition_node is not None: definition = definition_node.text else: definition = '<empty definition>' else: definition = '<unknown definition>' if role == Qt.DecorationRole: if header == self.HEADER_VARIABLE: return QVariant(IconLibrary.icon('variable')) if role == Qt.DisplayRole: var_name = get_variable_name(self._variable_nodes[row]) if header == self.HEADER_VARIABLE: return QVariant(var_name) if header == self.HEADER_DEFINITION: return QVariant(definition) if header == self.HEADER_COEFF_NAME: if 'coefficient_name' in node.attrib: return QVariant(node.get('coefficient_name')) return QVariant(var_name) if header == self.HEADER_STARTING_VAL: return QVariant(node.get('starting_value') or '') if role == Qt.EditRole: if header == self.HEADER_STARTING_VAL: return self.data(index, Qt.DisplayRole) if header == self.HEADER_COEFF_NAME: # give a clear coeff name if it's not set yet if 'coefficient_name' in node.attrib: return QVariant(node.get('coefficient_name')) return QVariant() if role == Qt.CheckStateRole: if header == self.HEADER_IGNORE: return QVariant(Qt.Checked if node.get('ignore') == 'True' else Qt.Unchecked) if header == self.HEADER_FIXED: return QVariant(Qt.Checked if node.get('keep_fixed') == 'True' else Qt.Unchecked) if role == Qt.FontRole: font = QtGui.QFont() if header == self.HEADER_VARIABLE: if node.get('ignore') != 'True': font.setBold(True) return QVariant(font) elif header == self.HEADER_COEFF_NAME and node.get('coefficient_name'): font.setBold(True) return QVariant(font) if role == Qt.ForegroundRole: # color default values of coefficient name as light gray if header == self.HEADER_COEFF_NAME: if 'coefficient_name' not in node.attrib: return QVariant(QtGui.QColor(Qt.gray)) if role == Qt.ToolTipRole: if header == self.HEADER_DEFINITION: # defs easily get cramped so show in tool tip as well return QVariant(definition) return QVariant()