def add_model_view_delegate(self): ''' See XmlController for documentation ''' # switch out the model for a custom one self.model = XmlModel_Models(self.xml_root, self.manager.project) self.view = XmlView(self.manager.base_widget) self.delegate = XmlItemDelegate(self.view)
class XmlController_Models(XmlController): def __init__(self, manager): ''' See XmlController for documentation ''' XmlController.__init__(self, manager) # Create popup menu actions p = ('add', "Create model from template", self._show_dialog_for_template_node) self.action_create_model_from_template = self.create_action(*p) p = ('estimation', "Run Estimation", self.run_estimation_for_selected) self.action_run_estimation = self.create_action(*p) p = ('', "Right click the individual groups (specification/<group>) to estimate", lambda: ()) self.action_show_how_to_estimate_groups = self.create_action(*p) p = ('estimation', "Run Estimation Group", self.run_estimation_for_selected_group) self.action_run_estimation_group = self.create_action(*p) p = ('submodel', "Edit Submodel", self._open_submodel_editor_for_selected) self.action_edit_submodel = self.create_action(*p) font = QFont() font.setBold(True) self.action_edit_submodel.setFont(font) # Create a list of available template nodes self.create_from_template_actions = [] template_nodes = self.project.findall('model_manager/templates/model_template') templates = dict((node.get('name'), node) for node in template_nodes) for template_name, template_node in templates.items(): callback = lambda x = template_node: self._show_dialog_for_template_node(x) action = self.create_action('clone', template_name, callback) self.create_from_template_actions.append(action) self.editor = None self.view.connect(self.view, SIGNAL('doubleClicked(const QModelIndex&)'), self._on_double_click) def add_model_view_delegate(self): ''' See XmlController for documentation ''' # switch out the model for a custom one self.model = XmlModel_Models(self.xml_root, self.manager.project) self.view = XmlView(self.manager.base_widget) self.delegate = XmlItemDelegate(self.view) def _on_double_click(self, index): node = index.internalPointer().node if node is None: return if index.column() == 0 and node.get('type') == 'submodel' and not node.get('inherited'): self._open_submodel_editor_for_selected() def run_estimation_for_selected(self): ''' Create an Estimation Run Dialog for for running all the submodels. ''' assert self.has_selected_item() model_name = self.selected_item().node.get('name') xml_config = self.manager.project.xml_config estimation_element = OpusEstimation(xml_config, model_name) self.manager.add_estimation_element(estimation_element) def run_estimation_for_selected_group(self): ''' Create an estimation run dialog for this model for running a all submodels within a submodel group. ''' assert self.has_selected_item() # Structure looks like: <model_item>/specfication/<group_item> # so model_index is parent of parent of the group index group_node = self.selected_item().node model_node = group_node.getparent().getparent() xml_config = self.manager.project.xml_config estimation_element = OpusEstimation(xml_config, model_node.get('name'), group_node.get('name')) self.manager.add_estimation_element(estimation_element) def _show_dialog_for_template_node(self, template_node): ''' generate a dialog for the selected template ''' dialog = DynamicTemplateDialog(template_node, self.project, self.view) if dialog.exec_() == dialog.Accepted: models_node = self.project.find('model_manager/models') self.model.insert_node(dialog.model_node, models_node) def create_model_from_template_callback(self, new_model_node): # do the actual inserting of the opus model into the project self.model.insertRow(0, self.selected_index(), new_model_node) update_models_to_run_lists() def _open_submodel_editor_for_selected(self): # assert self.has_selected_item() # submodel_node = self.selected_item().node # submodel_parent = submodel_node.getparent() # if self.editor is None: # self.editor = SubModelEditorOld(self.project) # editor = self.editor # editor.init_for_submodel_node(submodel_node) # if editor.exec_() == editor.Accepted: # self._update_submodel(submodel_node, editor.submodel_node) assert self.has_selected_item() submodel_node = self.selected_item().node if self.editor is None: self.editor = SubModelEditor(self.project) editor = self.editor editor.init_for_submodel_node(submodel_node) if editor.exec_() == editor.Accepted: self._update_submodel(submodel_node, editor.submodel_node) def _update_submodel(self, current_node, edited_node): ''' Updating a submodel node (current_node) based on an edited version of it (edited_node)''' # the effect of renaming a shadowing node is that a new (local) copy is created and # the inherited node is reinserted. If the user did not rename the node we overwrite # the old submodel with the new values. name_change = current_node.get('name') != edited_node.get('name') if self.project.is_shadowing(current_node) and name_change: parent_node = current_node.getparent() row = parent_node.index(current_node) new_submodel_node = self.project.insert_node(edited_node, parent_node, row) if new_submodel_node is None: msg = ('Tried to insert a new submodel (%s) but failed. ' 'The recent submodel changes have been lost.' %current_node.get('name')) logger.log_warning(msg) self.project.delete_node(current_node) else: for key in edited_node.attrib: current_node.attrib[key] = edited_node.attrib[key] for child in current_node: current_node.remove(child) for child in edited_node: current_node.append(child) self.project.dirty = True def process_custom_menu(self, point): ''' See XmlConfig.processCustomMenu for documentation ''' index = self.select_item_at(point) if not index: return node = self.selected_item().node menu = QMenu(self.view) if node.tag == 'models': submenu = QMenu(menu) # to populate with templates submenu.setTitle('Create model from template') for action in self.create_from_template_actions: submenu.addAction(action) menu.addMenu(submenu) if node.tag == 'model': # If the users right clicks a model, give them the option to # estimate it only if the model has a (non empty) specification # subnode. If the model holds subgroups -- inform the user how to # estimate them. spec_node = node.find('specification') submodels = None if spec_node is not None: submodels = spec_node.getchildren() if spec_node is not None and submodels: # check if its groups by type checking the first node # note: this is not a reliable method if models can have mixed # submodels and submodel groups. if submodels[0].tag == 'submodel': menu.addAction(self.action_run_estimation) else: menu.addAction(self.action_show_how_to_estimate_groups) if node.tag == 'submodel' and not node.get('inherited'): menu.addAction(self.action_edit_submodel) if node.tag == 'submodel_group': menu.addAction(self.action_run_estimation_group) self.add_default_menu_items_for_node(node, menu) if not menu.isEmpty(): menu.exec_(QCursor.pos())
class XmlController_Models(XmlController): def __init__(self, manager): ''' See XmlController for documentation ''' XmlController.__init__(self, manager) # Create popup menu actions p = ('add', "Create model from template", self._show_dialog_for_template_node) self.action_create_model_from_template = self.create_action(*p) p = ('estimation', "Run Estimation", self.run_estimation_for_selected) self.action_run_estimation = self.create_action(*p) p = ('', "Right click the individual groups (specification/<group>) to estimate", lambda: ()) self.action_show_how_to_estimate_groups = self.create_action(*p) p = ('estimation', "Run Estimation Group", self.run_estimation_for_selected_group) self.action_run_estimation_group = self.create_action(*p) p = ('submodel', "Edit Submodel", self._open_submodel_editor_for_selected) self.action_edit_submodel = self.create_action(*p) # Create a list of available template nodes self.create_from_template_actions = [] template_nodes = self.project.findall('model_manager/templates/model_template') templates = dict((node.get('name'), node) for node in template_nodes) for template_name, template_node in templates.items(): callback = lambda x = template_node: self._show_dialog_for_template_node(x) action = self.create_action('clone', template_name, callback) self.create_from_template_actions.append(action) self.editor = None def add_model_view_delegate(self): ''' See XmlController for documentation ''' # switch out the model for a custom one self.model = XmlModel_Models(self.xml_root, self.manager.project) self.view = XmlView(self.manager.base_widget) self.delegate = XmlItemDelegate(self.view) def run_estimation_for_selected(self): ''' Create an Estimation Run Dialog for for running all the submodels. ''' assert self.has_selected_item() model_name = self.selected_item().node.get('name') xml_config = self.manager.project.xml_config estimation_element = OpusEstimation(xml_config, model_name) self.manager.add_estimation_element(estimation_element) def run_estimation_for_selected_group(self): ''' Create an estimation run dialog for this model for running a all submodels within a submodel group. ''' assert self.has_selected_item() # Structure looks like: <model_item>/specfication/<group_item> # so model_index is parent of parent of the group index group_node = self.selected_item().node model_node = group_node.getparent().getparent() xml_config = self.manager.project.xml_config estimation_element = OpusEstimation(xml_config, model_node.get('name'), group_node.get('name')) self.manager.add_estimation_element(estimation_element) def _show_dialog_for_template_node(self, template_node): ''' generate a dialog for the selected template ''' dialog = DynamicTemplateDialog(template_node, self.project, self.view) if dialog.exec_() == dialog.Accepted: models_node = self.project.find('model_manager/models') self.model.insert_node(dialog.model_node, models_node) def create_model_from_template_callback(self, new_model_node): # do the actual inserting of the opus model into the project self.model.insertRow(0, self.selected_index(), new_model_node) update_models_to_run_lists() def _open_submodel_editor_for_selected(self): # assert self.has_selected_item() # submodel_node = self.selected_item().node # submodel_parent = submodel_node.getparent() # if self.editor is None: # self.editor = SubModelEditorOld(self.project) # editor = self.editor # editor.init_for_submodel_node(submodel_node) # if editor.exec_() == editor.Accepted: # self._update_submodel(submodel_node, editor.submodel_node) assert self.has_selected_item() submodel_node = self.selected_item().node if self.editor is None: self.editor = SubModelEditor(self.project) editor = self.editor editor.init_for_submodel_node(submodel_node) if editor.exec_() == editor.Accepted: self._update_submodel(submodel_node, editor.submodel_node) def _update_submodel(self, current_node, edited_node): ''' Updating a submodel node (current_node) based on an edited version of it (edited_node)''' # the effect of renaming a shadowing node is that a new (local) copy is created and # the inherited node is reinserted. If the user did not rename the node we overwrite # the old submodel with the new values. name_change = current_node.get('name') != edited_node.get('name') if self.project.is_shadowing(current_node) and name_change: parent_node = current_node.getparent() row = parent_node.index(current_node) new_submodel_node = self.project.insert_node(edited_node, parent_node, row) if new_submodel_node is None: msg = ('Tried to insert a new submodel (%s) but failed. ' 'The recent submodel changes have been lost.' %current_node.get('name')) logger.log_warning(msg) self.project.delete_node(current_node) else: for key in edited_node.attrib: current_node.attrib[key] = edited_node.attrib[key] for child in current_node: current_node.remove(child) for child in edited_node: current_node.append(child) self.project.dirty = True def add_custom_menu_items_for_node(self, node, menu): if node.tag == 'models': submenu = QMenu(menu) # to populate with templates submenu.setTitle('Create model from template') for action in self.create_from_template_actions: submenu.addAction(action) menu.addMenu(submenu) if node.tag == 'model': # If the users right clicks a model, give them the option to # estimate it only if the model has a (non empty) specification # subnode. If the model holds subgroups -- inform the user how to # estimate them. spec_node = node.find('specification') submodels = None if spec_node is not None: submodels = spec_node.getchildren() if spec_node is not None and submodels: # check if its groups by type checking the first node # note: this is not a reliable method if models can have mixed # submodels and submodel groups. if submodels[0].tag == 'submodel': menu.addAction(self.action_run_estimation) else: menu.addAction(self.action_show_how_to_estimate_groups) if node.tag == 'submodel' and not node.get('inherited'): menu.addAction(self.action_edit_submodel) if node.tag == 'submodel_group': menu.addAction(self.action_run_estimation_group) # In this menu, the first custom action is always the default action if not menu.isEmpty(): menu.setDefaultAction(menu.actions()[0])