class AdditionListSlave(SearchSlave): """A slave that offers a simple list and its management. This slave also has the option to display a small message right next to the buttons """ domain = 'stoq' toplevel_name = gladefile = 'AdditionListSlave' widgets = ('add_button', 'delete_button', 'klist', 'list_vbox', 'edit_button') gsignal('on-edit-item', object) gsignal('on-add-item', object) gsignal('before-delete-items', object) gsignal('after-delete-items') def __init__(self, store, columns=None, editor_class=None, klist_objects=None, visual_mode=False, restore_name=None, tree=False): """ Creates a new AdditionListSlave object :param store: a store :param columns: column definitions :type columns: sequence of :class:`kiwi.ui.objectlist.Columns` :param editor_class: the window that is going to be open when user clicks on add_button or edit_button. :type: editor_class: a :class:`stoqlib.gui.editors.BaseEditor` subclass :param klist_objects: initial objects to insert into the list :param visual_mode: if we are working on visual mode, that means, not possible to edit the model on this object type visual_mode: bool :param restore_name: the name used to save and restore the columns on a cache system (e.g. pickle) :type restore_name: basestring :param tree: Indication of which kind of list we are adding. If `True` ObjectTree otherwise ObjectList will be added """ columns = columns or self.get_columns() SearchSlave.__init__(self, columns=columns, restore_name=restore_name, store=store) self.tree = tree self.klist = ObjectTree() if tree else ObjectList() self.list_vbox.add(self.klist) self.list_vbox.show_all() if not self.columns: raise StoqlibError("columns must be specified") self.visual_mode = visual_mode self.store = store self.set_editor(editor_class) self._can_edit = True self._callback_id = None if self.visual_mode: self.hide_add_button() self.hide_edit_button() self.hide_del_button() items = klist_objects or self.get_items() self._setup_klist(items) self._update_sensitivity() def _setup_klist(self, klist_objects): self.klist.set_columns(self.columns) self.klist.set_selection_mode(gtk.SELECTION_MULTIPLE) if self.tree: (self.klist.append(obj.parent_item, obj) for obj in klist_objects) else: self.klist.add_list(klist_objects) if self.visual_mode: self.klist.set_sensitive(False) def _update_sensitivity(self, *args): if self.visual_mode: return can_delete = _can_edit = True objs = self.get_selection() if not objs: _can_edit = can_delete = False elif len(objs) > 1: _can_edit = False self.add_button.set_sensitive(True) self.edit_button.set_sensitive(_can_edit) self.delete_button.set_sensitive(can_delete) def _edit_model(self, model=None, parent=None): edit_mode = model result = self.run_editor(model) if not result: return if edit_mode: self.emit('on-edit-item', result) self.klist.update(result) else: if self.tree: self.klist.append(parent, result) else: self.klist.append(result) # Emit the signal after we added the item to the list to be able to # check the length of the list in our validation callbacks. self.emit('on-add-item', result) # As we have a selection extended mode for kiwi list, we # need to unselect everything before select the new instance. self.klist.unselect_all() self.klist.select(result) self._update_sensitivity() def _edit(self): if not self._can_edit: return objs = self.get_selection() qty = len(objs) if qty != 1: raise SelectionError( ("Please select only one item before choosing Edit." "\nThere are currently %d items selected") % qty) self._edit_model(objs[0]) def _clear(self): objs = self.get_selection() qty = len(objs) if qty < 1: raise SelectionError('There are no objects selected') msg = stoqlib_ngettext(_('Delete this item?'), _('Delete these %d items?') % qty, qty) delete_label = stoqlib_ngettext(_("Delete item"), _("Delete items"), qty) keep_label = stoqlib_ngettext(_("Keep it"), _("Keep them"), qty) if not yesno(msg, gtk.RESPONSE_NO, delete_label, keep_label): return self.emit('before-delete-items', objs) if qty == len(self.klist): self.klist.clear() else: for obj in objs: self.klist.remove(obj) self.klist.unselect_all() self._update_sensitivity() self.emit('after-delete-items') # # Hooks # def get_items(self): return [] def get_columns(self): raise NotImplementedError("get_columns must be implemented in " "subclasses") def run_editor(self, model): """This can be overriden to provide a custom run_dialog line, or a conversion function for the model """ if self._editor_class is None: raise TypeError( "%s cannot create or edit items without the editor_class " "argument set" % (self.__class__.__name__)) self.store.savepoint('before_run_editor_addition') retval = run_dialog(self._editor_class, None, store=self.store, model=model) if not retval: self.store.rollback_to_savepoint('before_run_editor_addition') return retval def delete_model(self, model): """Deletes a model, can be overridden in subclass :param model: model to delete """ model.__class__.delete(model.id, store=self.store) # # Public API # def add_extra_button(self, label=None, stock=None): """Add an extra button on the this slave The extra button will be appended at the end of the button box, the one containing the add/edit/delete buttons :param label: label of the button, can be ``None`` if stock is passed :param stock: stock label of the button, can be ``None`` if label is passed :param returns: the button added :rtype: gtk.Button """ if label is None and stock is None: raise TypeError("You need to provide a label or a stock argument") button = gtk.Button(label=label, stock=stock) button.set_property('can_focus', True) self.button_box.pack_end(button, False, False) button.show() return button def set_message(self, message, details_callback=None): """Display a simple message on a label, next to the add, edit, delete buttons :param message: a message with properly escaped markup """ self.message_hbox.set_visible(True) self.message_details_button.set_visible(bool(details_callback)) if details_callback: if self._callback_id: self.message_details_button.disconnect(self._callback_id) self._callback_id = self.message_details_button.connect( 'clicked', details_callback) self.message_label.set_markup(message) def clear_message(self): self.message_hbox.set_visible(False) def get_selection(self): # XXX: add get_selected_rows and raise exceptions if not in the # right mode if self.klist.get_selection_mode() == gtk.SELECTION_MULTIPLE: return self.klist.get_selected_rows() selection = self.klist.get_selected() if not selection: return [] return [selection] def hide_add_button(self): self.add_button.hide() def hide_edit_button(self): self._can_edit = False self.edit_button.hide() def hide_del_button(self): self.delete_button.hide() def set_editor(self, editor_class): if editor_class and not issubclass(editor_class, (BaseEditor, BaseWizard)): raise TypeError("editor_class must be a BaseEditor subclass") self._editor_class = editor_class # # Signal handlers # def on_klist__row_activated(self, *args): self._edit() def on_klist__selection_changed(self, *args): self._update_sensitivity() def on_add_button__clicked(self, button): self._edit_model() def on_edit_button__clicked(self, button): self._edit() def on_delete_button__clicked(self, button): self._clear()
class AdditionListSlave(SearchSlave): """A slave that offers a simple list and its management. This slave also has the option to display a small message right next to the buttons """ domain = 'stoq' toplevel_name = gladefile = 'AdditionListSlave' widgets = ('add_button', 'delete_button', 'klist', 'list_vbox', 'edit_button') gsignal('before-edit-item', object, retval=object) gsignal('on-edit-item', object) gsignal('on-add-item', object) gsignal('before-delete-items', object) gsignal('after-delete-items') def __init__(self, store, columns=None, editor_class=None, klist_objects=None, visual_mode=False, restore_name=None, tree=False): """ Creates a new AdditionListSlave object :param store: a store :param columns: column definitions :type columns: sequence of :class:`kiwi.ui.objectlist.Columns` :param editor_class: the window that is going to be open when user clicks on add_button or edit_button. :type: editor_class: a :class:`stoqlib.gui.editors.BaseEditor` subclass :param klist_objects: initial objects to insert into the list :param visual_mode: if we are working on visual mode, that means, not possible to edit the model on this object type visual_mode: bool :param restore_name: the name used to save and restore the columns on a cache system (e.g. pickle) :type restore_name: basestring :param tree: Indication of which kind of list we are adding. If `True` ObjectTree otherwise ObjectList will be added """ columns = columns or self.get_columns() SearchSlave.__init__(self, columns=columns, restore_name=restore_name, store=store) self.tree = tree self.klist = ObjectTree() if tree else ObjectList() self.list_vbox.add(self.klist) self.list_vbox.show_all() if not self.columns: raise StoqlibError("columns must be specified") self.visual_mode = visual_mode self.store = store self.set_editor(editor_class) self._can_edit = True self._callback_id = None if self.visual_mode: self.hide_add_button() self.hide_edit_button() self.hide_del_button() items = klist_objects or self.get_items() self._setup_klist(items) self._update_sensitivity() def _setup_klist(self, klist_objects): self.klist.set_columns(self.columns) self.klist.set_selection_mode(gtk.SELECTION_MULTIPLE) if self.tree: (self.klist.append(obj.parent_item, obj) for obj in klist_objects) else: self.klist.add_list(klist_objects) if self.visual_mode: self.klist.set_sensitive(False) def _update_sensitivity(self, *args): if self.visual_mode: return can_delete = _can_edit = True objs = self.get_selection() if not objs: _can_edit = can_delete = False elif len(objs) > 1: _can_edit = False self.add_button.set_sensitive(True) self.edit_button.set_sensitive(_can_edit) self.delete_button.set_sensitive(can_delete) def _edit_model(self, model=None, parent=None): edit_mode = model result = self.emit('before-edit-item', model) if result is None: result = self.run_editor(model) if not result: return if edit_mode: self.emit('on-edit-item', result) self.klist.update(result) else: if self.tree: self.klist.append(parent, result) else: self.klist.append(result) # Emit the signal after we added the item to the list to be able to # check the length of the list in our validation callbacks. self.emit('on-add-item', result) # As we have a selection extended mode for kiwi list, we # need to unselect everything before select the new instance. self.klist.unselect_all() self.klist.select(result) self._update_sensitivity() def _edit(self): if not self._can_edit: return objs = self.get_selection() qty = len(objs) if qty != 1: raise SelectionError( ("Please select only one item before choosing Edit." "\nThere are currently %d items selected") % qty) self._edit_model(objs[0]) def _clear(self): objs = self.get_selection() qty = len(objs) if qty < 1: raise SelectionError('There are no objects selected') msg = stoqlib_ngettext( _('Delete this item?'), _('Delete these %d items?') % qty, qty) delete_label = stoqlib_ngettext( _("Delete item"), _("Delete items"), qty) keep_label = stoqlib_ngettext( _("Keep it"), _("Keep them"), qty) if not yesno(msg, gtk.RESPONSE_NO, delete_label, keep_label): return self.emit('before-delete-items', objs) if qty == len(self.klist): self.klist.clear() else: for obj in objs: self.klist.remove(obj) self.klist.unselect_all() self._update_sensitivity() self.emit('after-delete-items') # # Hooks # def get_items(self): return [] def get_columns(self): raise NotImplementedError("get_columns must be implemented in " "subclasses") def run_editor(self, model): """This can be overriden to provide a custom run_dialog line, or a conversion function for the model """ if self._editor_class is None: raise TypeError( "%s cannot create or edit items without the editor_class " "argument set" % (self.__class__.__name__)) self.store.savepoint('before_run_editor_addition') retval = run_dialog(self._editor_class, None, store=self.store, model=model) if not retval: self.store.rollback_to_savepoint('before_run_editor_addition') return retval def delete_model(self, model): """Deletes a model, can be overridden in subclass :param model: model to delete """ model.__class__.delete(model.id, store=self.store) # # Public API # def add_extra_button(self, label=None, stock=None): """Add an extra button on the this slave The extra button will be appended at the end of the button box, the one containing the add/edit/delete buttons :param label: label of the button, can be ``None`` if stock is passed :param stock: stock label of the button, can be ``None`` if label is passed :param returns: the button added :rtype: gtk.Button """ if label is None and stock is None: raise TypeError("You need to provide a label or a stock argument") button = gtk.Button(label=label, stock=stock) button.set_property('can_focus', True) self.button_box.pack_end(button, False, False) button.show() return button def set_message(self, message, details_callback=None): """Display a simple message on a label, next to the add, edit, delete buttons :param message: a message with properly escaped markup """ self.message_hbox.set_visible(True) self.message_details_button.set_visible(bool(details_callback)) if details_callback: if self._callback_id: self.message_details_button.disconnect(self._callback_id) self._callback_id = self.message_details_button.connect( 'clicked', details_callback) self.message_label.set_markup(message) def clear_message(self): self.message_hbox.set_visible(False) def get_selection(self): # XXX: add get_selected_rows and raise exceptions if not in the # right mode if self.klist.get_selection_mode() == gtk.SELECTION_MULTIPLE: return self.klist.get_selected_rows() selection = self.klist.get_selected() if not selection: return [] return [selection] def hide_add_button(self): self.add_button.hide() def hide_edit_button(self): self._can_edit = False self.edit_button.hide() def hide_del_button(self): self.delete_button.hide() def set_editor(self, editor_class): if editor_class and not issubclass(editor_class, (BaseEditor, BaseWizard)): raise TypeError("editor_class must be a BaseEditor subclass") self._editor_class = editor_class # # Signal handlers # def on_klist__row_activated(self, *args): self._edit() def on_klist__selection_changed(self, *args): self._update_sensitivity() def on_add_button__clicked(self, button): self._edit_model() def on_edit_button__clicked(self, button): self._edit() def on_delete_button__clicked(self, button): self._clear()
class GTKProject(SlaveDelegate): """A facade of kmcos.types.Project so that pygtk can display in a TreeView. """ def __init__(self, parent, menubar): self.project_data = ObjectTree([ Column('name', use_markup=True, data_type=str, sorted=True), Column('info') ]) self.project_data.connect('row-activated', self.on_row_activated) self.model_tree = Project() self._set_treeview_hooks() self.menubar = menubar self.set_parent(parent) self.filename = '' self.undo_stack = UndoStack(self.model_tree.__repr__, self.import_file, self.project_data.select, menubar, self.meta, 'Initialization') SlaveDelegate.__init__(self, toplevel=self.project_data) def _set_treeview_hooks(self): """Fudge function to import to access function to kmcos.types.Project to kmcos.gui.GTKProject. """ self.project_data.clear() # Meta self.meta = self.project_data.append(None, self.model_tree.meta) self.model_tree.meta = self.meta # Layer List self.model_tree.add_layer = self.add_layer self.layer_list = self.project_data.append(None, self.model_tree.layer_list) self.get_layers = lambda: \ sorted(self.project_data.get_descendants(self.layer_list), key=lambda x: x.name) self.model_tree.get_layers = self.get_layers self.lattice = self.layer_list # Parameter List self.parameter_list = self.project_data.append( None, self.model_tree.parameter_list) self.add_parameter = lambda parameter: \ self.project_data.append(self.parameter_list, parameter) self.model_tree.add_parameter = self.add_parameter self.get_parameters = lambda: \ sorted(self.project_data.get_descendants(self.parameter_list), key=lambda x: x.name) self.model_tree.get_parameters = self.get_parameters # Species List self.species_list = self.project_data.append( None, self.model_tree.species_list) self.add_species = lambda species: \ self.project_data.append(self.species_list, species) self.model_tree.add_species = self.add_species self.get_speciess = lambda: \ sorted(self.project_data.get_descendants(self.species_list), key=lambda x: x.name) self.model_tree.get_speciess = self.get_speciess # Process List self.process_list = self.project_data.append( None, self.model_tree.process_list) self.add_process = lambda process:\ self.project_data.append(self.process_list, process) self.model_tree.add_process = self.add_process self.get_processes = lambda: \ sorted(self.project_data.get_descendants(self.process_list), key=lambda x: x.name) self.model_tree.get_processes = self.get_processes # Output List self.output_list = self.project_data.append( None, self.model_tree.output_list) self.add_output = lambda output:\ self.project_data.append(self.output_list, output) self.model_tree.add_output = self.add_output self.get_outputs = lambda: \ sorted(self.project_data.get_descendants(self.output_list), key=lambda x: x.name) self.model_tree.get_outputs = self.get_outputs def add_layer(self, layer): self.project_data.append(self.layer_list, layer) if len(self.get_layers()) == 1: self.set_default_layer(layer.name) self.set_substrate_layer(layer.name) return layer def set_default_species(self, species): self.model_tree.species_list.default_species = species def set_substrate_layer(self, layer): self.model_tree.layer_list.substrate_layer = layer def set_default_layer(self, layer): self.model_tree.layer_list.default_layer = layer def update(self, model): """Update the object tree.""" self.project_data.update(model) def on_row_activated(self, _tree, data): if isinstance(data, Layer): data.active = not data.active def get_name(self): """Return project name.""" if self.filename: return os.path.basename(self.filename) else: return 'Untitled' def __repr__(self): return str(self.model_tree) def import_file(self, filename): """Import XML project file into editor GUI, unfolding the object tree. """ self.filename = filename self.model_tree.import_file(filename) self.expand_all() def expand_all(self): """Expand all list of the project tree """ self.project_data.expand(self.species_list) self.project_data.expand(self.layer_list) self.project_data.expand(self.parameter_list) self.project_data.expand(self.process_list) self.project_data.expand(self.output_list) def on_key_press(self, _, event): """When the user hits the keyboard focusing the treeview this event is triggered. Right now the only supported function is to deleted the selected item """ selection = self.project_data.get_selected() if gtk.gdk.keyval_name(event.keyval) == 'Delete': if (isinstance(selection, Species) or isinstance(selection, Process) or isinstance(selection, Parameter) or isinstance(selection, Layer)): if kiwi.ui.dialogs.yesno( "Do you really want to delete '%s'?" \ % selection.name) == gtk.RESPONSE_YES: self.project_data.remove(selection) def on_project_data__selection_changed(self, _, elem): """When a new item is selected in the treeview this function loads the main area of the window with the corresponding form and data. """ slave = self.get_parent().get_slave('workarea') if slave: self.get_parent().detach_slave('workarea') if isinstance(elem, Layer): if self.meta.model_dimension in [1, 3]: self.get_parent().toast('Only 2d supported') return self.undo_stack.start_new_action('Edit Layer %s' % elem.name, elem) form = LayerEditor(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Meta): self.undo_stack.start_new_action('Edit Meta', elem) meta_form = MetaForm(self.meta, self) self.get_parent().attach_slave('workarea', meta_form) meta_form.focus_toplevel() meta_form.focus_topmost() elif isinstance(elem, OutputList): self.undo_stack.start_new_action('Edit Output', elem) form = OutputForm(self.output_list, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Parameter): self.undo_stack.start_new_action('Edit Parameter %s' % elem.name, elem) form = ParameterForm(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Process): if self.meta.model_dimension in [1, 3]: self.get_parent().toast('Only 2d supported') return self.undo_stack.start_new_action('Edit Process %s' % elem.name, elem) form = ProcessForm(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, ProcessList): if self.meta.model_dimension in [1, 3]: self.get_parent().toast('Only 2d supported') return self.undo_stack.start_new_action('Batch process editing', elem) form = BatchProcessForm(self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Species): self.undo_stack.start_new_action('Edit species', elem) form = SpeciesForm(elem, self.project_data) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, SpeciesList): self.undo_stack.start_new_action('Edit default species', elem) form = SpeciesListForm(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, LayerList): self.undo_stack.start_new_action('Edit lattice', elem) dimension = self.meta.model_dimension form = LatticeForm(elem, dimension, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() else: self.get_parent().toast('Not implemented, yet(%s).' % type(elem))
class GTKProject(SlaveDelegate): """A facade of kmos.types.Project so that pygtk can display in a TreeView. """ def __init__(self, parent, menubar): self.project_data = ObjectTree([Column('name', use_markup=True, data_type=str, sorted=True), Column('info')]) self.project_data.connect('row-activated', self.on_row_activated) self.model_tree = Project() self._set_treeview_hooks() self.menubar = menubar self.set_parent(parent) self.filename = '' self.undo_stack = UndoStack( self.model_tree.__repr__, self.import_xml_file, self.project_data.select, menubar, self.meta, 'Initialization') SlaveDelegate.__init__(self, toplevel=self.project_data) def _set_treeview_hooks(self): """Fudge function to import to access function to kmos.types.Project to kmos.gui.GTKProject. """ self.project_data.clear() # Meta self.meta = self.project_data.append(None, self.model_tree.meta) self.model_tree.meta = self.meta # Layer List self.model_tree.add_layer = self.add_layer self.layer_list = self.project_data.append(None, self.model_tree.layer_list) self.get_layers = lambda :\ sorted(self.project_data.get_descendants(self.layer_list), key=lambda x: x.name) self.model_tree.get_layers = self.get_layers self.lattice = self.layer_list # Parameter List self.parameter_list = self.project_data.append(None, self.model_tree.parameter_list) self.add_parameter = lambda parameter :\ self.project_data.append(self.parameter_list, parameter) self.model_tree.add_parameter = self.add_parameter self.get_parameters = lambda :\ sorted(self.project_data.get_descendants(self.parameter_list), key=lambda x: x.name) self.model_tree.get_parameters = self.get_parameters # Species List self.species_list = self.project_data.append(None, self.model_tree.species_list) self.add_species = lambda species :\ self.project_data.append(self.species_list, species) self.model_tree.add_species = self.add_species self.get_speciess = lambda :\ sorted(self.project_data.get_descendants(self.species_list), key=lambda x: x.name) self.model_tree.get_speciess = self.get_speciess # Process List self.process_list = self.project_data.append(None, self.model_tree.process_list) self.add_process = lambda process:\ self.project_data.append(self.process_list, process) self.model_tree.add_process = self.add_process self.get_processes = lambda :\ sorted(self.project_data.get_descendants(self.process_list), key=lambda x: x.name) self.model_tree.get_processes = self.get_processes # Output List self.output_list = self.project_data.append(None, self.model_tree.output_list) self.add_output = lambda output:\ self.project_data.append(self.output_list, output) self.model_tree.add_output = self.add_output self.get_outputs = lambda : \ sorted(self.project_data.get_descendants(self.output_list), key=lambda x: x.name) self.model_tree.get_outputs = self.get_outputs def add_layer(self, layer): self.project_data.append(self.layer_list, layer) if len(self.get_layers()) == 1 : self.set_default_layer(layer.name) self.set_substrate_layer(layer.name) def set_default_species(self, species): self.model_tree.species_list.default_species = species def set_substrate_layer(self, layer): self.model_tree.layer_list.substrate_layer = layer def set_default_layer(self, layer): self.model_tree.layer_list.default_layer = layer def update(self, model): self.project_data.update(model) def on_row_activated(self, tree, data): if isinstance(data, Layer): data.active = not data.active def get_name(self): if self.filename: return os.path.basename(self.filename) else: return 'Untitled' def __repr__(self): return str(self.model_tree) def import_xml_file(self, filename): self.model_tree.import_xml_file(filename) self.expand_all() def expand_all(self): """Expand all list of the project tree """ self.project_data.expand(self.species_list) self.project_data.expand(self.layer_list) self.project_data.expand(self.parameter_list) self.project_data.expand(self.process_list) self.project_data.expand(self.output_list) def on_key_press(self, _, event): """When the user hits the keyboard focusing the treeview this event is triggered. Right now the only supported function is to deleted the selected item """ selection = self.project_data.get_selected() if gtk.gdk.keyval_name(event.keyval) == 'Delete': if(isinstance(selection, Species) or isinstance(selection, Process) or isinstance(selection, Parameter) or isinstance(selection, Layer)): if kiwi.ui.dialogs.yesno( "Do you really want to delete '%s'?" \ % selection.name) == gtk.RESPONSE_YES: self.project_data.remove(selection) def on_project_data__selection_changed(self, _, elem): """When a new item is selected in the treeview this function loads the main area of the window with the corresponding form and data. """ slave = self.get_parent().get_slave('workarea') if slave: self.get_parent().detach_slave('workarea') if isinstance(elem, Layer): if self.meta.model_dimension in [1, 3]: self.get_parent().toast('Only 2d supported') return self.undo_stack.start_new_action('Edit Layer %s' % elem.name, elem) form = LayerEditor(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Meta): self.undo_stack.start_new_action('Edit Meta', elem) meta_form = MetaForm(self.meta, self) self.get_parent().attach_slave('workarea', meta_form) meta_form.focus_toplevel() meta_form.focus_topmost() elif isinstance(elem, OutputList): self.undo_stack.start_new_action('Edit Output', elem) form = OutputForm(self.output_list, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Parameter): self.undo_stack.start_new_action('Edit Parameter %s' % elem.name, elem) form = ParameterForm(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Process): if self.meta.model_dimension in [1, 3]: self.get_parent().toast('Only 2d supported') return self.undo_stack.start_new_action('Edit Process %s' % elem.name, elem) form = ProcessForm(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, ProcessList): if self.meta.model_dimension in [1, 3]: self.get_parent().toast('Only 2d supported') return self.undo_stack.start_new_action('Batch process editing', elem) form = BatchProcessForm(self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, Species): self.undo_stack.start_new_action('Edit species', elem) form = SpeciesForm(elem, self.project_data) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, SpeciesList): self.undo_stack.start_new_action('Edit default species', elem) form = SpeciesListForm(elem, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() elif isinstance(elem, LayerList): self.undo_stack.start_new_action('Edit lattice', elem) dimension = self.meta.model_dimension form = LatticeForm(elem, dimension, self) self.get_parent().attach_slave('workarea', form) form.focus_topmost() else: self.get_parent().toast('Not implemented, yet(%s).' % type(elem))