############################################################ # FlatCAM: 2D Post-processing for Manufacturing # # http://caram.cl/software/flatcam # # Author: Juan Pablo Caram (c) # # Date: 4/20/2014 # # MIT Licence # ############################################################ import inspect # TODO: Remove from gi.repository import Gtk, GdkPixbuf, GLib from FlatCAMObj import * from FlatCAM_GTK import FlatCAMApp class ObjectCollection: classdict = { "gerber": FlatCAMGerber, "excellon": FlatCAMExcellon, "cncjob": FlatCAMCNCjob, "geometry": FlatCAMGeometry } icon_files = { "gerber": "share/flatcam_icon16.png", "excellon": "share/drill16.png", "cncjob": "share/cnc16.png", "geometry": "share/geometry16.png" } def __init__(self): ### Icons for the list view self.icons = {} for kind in ObjectCollection.icon_files: self.icons[kind] = GdkPixbuf.Pixbuf.new_from_file(ObjectCollection.icon_files[kind]) ### GUI List components ## Model self.store = Gtk.ListStore(FlatCAMObj) ## View self.view = Gtk.TreeView(model=self.store) #self.view.connect("row_activated", self.on_row_activated) self.tree_selection = self.view.get_selection() self.change_subscription = self.tree_selection.connect("changed", self.on_list_selection_change) ## Renderers # Icon renderer_pixbuf = Gtk.CellRendererPixbuf() column_pixbuf = Gtk.TreeViewColumn("Type", renderer_pixbuf) def _set_cell_icon(column, cell, model, it, data): obj = model.get_value(it, 0) cell.set_property('pixbuf', self.icons[obj.kind]) column_pixbuf.set_cell_data_func(renderer_pixbuf, _set_cell_icon) self.view.append_column(column_pixbuf) # Name renderer_text = Gtk.CellRendererText() column_text = Gtk.TreeViewColumn("Name", renderer_text) def _set_cell_text(column, cell, model, it, data): obj = model.get_value(it, 0) cell.set_property('text', obj.options["name"]) column_text.set_cell_data_func(renderer_text, _set_cell_text) self.view.append_column(column_text) def print_list(self): iterat = self.store.get_iter_first() while iterat is not None: obj = self.store[iterat][0] print obj iterat = self.store.iter_next(iterat) def delete_all(self): FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_all()") self.store.clear() def delete_active(self): FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_active()") try: model, treeiter = self.tree_selection.get_selected() self.store.remove(treeiter) except: pass def on_list_selection_change(self, selection): """ Callback for change in selection on the objects' list. Instructs the new selection to build the UI for its options. :param selection: Ignored. :return: None """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.on_list_selection_change()") active = self.get_active() active.build_ui() def set_active(self, name): """ Sets an object as the active object in the program. Same as `set_list_selection()`. :param name: Name of the object. :type name: str :return: None """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.set_active()") self.set_list_selection(name) def get_active(self): FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_active()") try: model, treeiter = self.tree_selection.get_selected() return model[treeiter][0] except (TypeError, ValueError): return None def set_list_selection(self, name): """ Sets which object should be selected in the list. :param name: Name of the object. :rtype name: str :return: None """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.set_list_selection()") iterat = self.store.get_iter_first() while iterat is not None and self.store[iterat][0].options["name"] != name: iterat = self.store.iter_next(iterat) self.tree_selection.select_iter(iterat) def append(self, obj, active=False): """ Add a FlatCAMObj the the collection. This method is thread-safe. :param obj: FlatCAMObj to append :type obj: FlatCAMObj :param active: If it is to become the active object after appending :type active: bool :return: None """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.append()") def guitask(): self.store.append([obj]) if active: self.set_list_selection(obj.options["name"]) GLib.idle_add(guitask) def get_names(self): """ Gets a list of the names of all objects in the collection. :return: List of names. :rtype: list """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_names()") names = [] iterat = self.store.get_iter_first() while iterat is not None: obj = self.store[iterat][0] names.append(obj.options["name"]) iterat = self.store.iter_next(iterat) return names def get_bounds(self): """ Finds coordinates bounding all objects in the collection. :return: [xmin, ymin, xmax, ymax] :rtype: list """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_bounds()") # TODO: Move the operation out of here. xmin = Inf ymin = Inf xmax = -Inf ymax = -Inf iterat = self.store.get_iter_first() while iterat is not None: obj = self.store[iterat][0] try: gxmin, gymin, gxmax, gymax = obj.bounds() xmin = min([xmin, gxmin]) ymin = min([ymin, gymin]) xmax = max([xmax, gxmax]) ymax = max([ymax, gymax]) except: FlatCAMApp.App.log.warning("DEV WARNING: Tried to get bounds of empty geometry.") iterat = self.store.iter_next(iterat) return [xmin, ymin, xmax, ymax] def get_list(self): """ Returns a list with all FlatCAMObj. :return: List with all FlatCAMObj. :rtype: list """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_list()") collection_list = [] iterat = self.store.get_iter_first() while iterat is not None: obj = self.store[iterat][0] collection_list.append(obj) iterat = self.store.iter_next(iterat) return collection_list def get_by_name(self, name): """ Fetches the FlatCAMObj with the given `name`. :param name: The name of the object. :type name: str :return: The requested object or None if no such object. :rtype: FlatCAMObj or None """ FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_by_name()") iterat = self.store.get_iter_first() while iterat is not None: obj = self.store[iterat][0] if obj.options["name"] == name: return obj iterat = self.store.iter_next(iterat) return None # def change_name(self, old_name, new_name): # """ # Changes the name of `FlatCAMObj` named `old_name` to `new_name`. # # :param old_name: Name of the object to change. # :type old_name: str # :param new_name: New name. # :type new_name: str # :return: True if name change succeeded, False otherwise. Will fail # if no object with `old_name` is found. # :rtype: bool # """ # print inspect.stack()[1][3], "--> OC.change_name()" # iterat = self.store.get_iter_first() # while iterat is not None: # obj = self.store[iterat][0] # if obj.options["name"] == old_name: # obj.options["name"] = new_name # self.store.row_changed(0, iterat) # return True # iterat = self.store.iter_next(iterat) # return False