def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self.gstat = GStat() self.gstat.connect('file-loaded', lambda w, f: self._load(f)) self.show()
def __init__(self, *a, **kw): Gtk.VBox.__init__(self, *a, **kw) self.use_double_click = False self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) self.no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = Gtk.ListStore(str) self.tv = Gtk.TreeView() self.default_font = self.tv.get_style().font_desc.to_string() self.tv.modify_font(Pango.FontDescription(self.default_font)) self.tv.set_model(self.model) self.cell = Gtk.CellRendererText() self.col = Gtk.TreeViewColumn("Command") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) self.tv.get_selection().set_mode(Gtk.SelectionMode.NONE) scroll = Gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC scroll.props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC self.entry = Gtk.Entry() print("Icon from stock") self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "gtk-ok") self.entry.modify_font(Pango.FontDescription(self.default_font)) self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True, True, 0) self.pack_start(self.entry, False, False, 0) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on())) self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) # this time lambda with two parameters, as not all homed will send also the unhomed joints self.gstat.connect('not-all-homed', lambda w,uj: self.set_sensitive(self.no_home_required) ) self.reload() self.show_all()
def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self._reload_filename = None self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.gstat.connect('reload-display', self.reloadfile) self.show()
def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. try: inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) macros = self.inifile.findall("MACROS", "MACRO") sub_path = self.inifile.find("RS274NGC", "SUBROUTINE_PATH")or '~/linuxcnc/nc_files/macros' except: no_home_required = 1 macros = None sub_path = '~/linuxcnc/nc_files/macros' #path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.foldername = os.path.expanduser(sub_path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Macro Commands") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on() and ( self.is_all_homed() or no_home_required ) )) self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) self.reload() self.show_all()
def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) self.no_home_required = int( self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Command") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on())) self.gstat.connect( 'interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) # this time lambda with two parameters, as not all homed will send also the unhomed joints self.gstat.connect( 'not-all-homed', lambda w, uj: self.set_sensitive(self.no_home_required)) self.reload() self.show_all()
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gproperties__ = { 'view' : ( gobject.TYPE_STRING, 'View type', 'Default view: p, x, y, y2, z, z2', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro' : ( gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units' : ( gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative' : ( gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded' : ( gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option' : ( gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits' : ( gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot' : ( gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity' : ( gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program' : ( gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids' : ( gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool' : ( gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg' : ( gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_lathe_radius' : ( gobject.TYPE_BOOLEAN, 'Show Lathe Radius', 'Show X axis in Radius', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'grid_size' : ( gobject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode' : ( gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_default_controls' : ( gobject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.show() def fileloaded(self,w,f): try: self._load(f) except AttributeError,detail: #AttributeError: 'NoneType' object has no attribute 'gl_end' print 'hal_gremlin: continuing after',detail
def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.use_double_click = False self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) self.no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.default_font = self.tv.get_style().font_desc.to_string() self.tv.modify_font(pango.FontDescription(self.default_font)) self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Command") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) self.tv.get_selection().set_mode(gtk.SELECTION_NONE) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.modify_font(pango.FontDescription(self.default_font)) self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on())) self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) # this time lambda with two parameters, as not all homed will send also the unhomed joints self.gstat.connect('not-all-homed', lambda w,uj: self.set_sensitive(self.no_home_required) ) self.reload() self.show_all()
def __init__(self, *a, **kw): gobject.GObject.__init__(self) ini_filename = os.environ.get('INI_FILE_NAME') if ini_filename is None: ini_filename = get_linuxcnc_ini_file() if ini_filename is not None: os.putenv('INI_FILE_NAME', ini_filename) os.environ['INI_FILE_NAME'] = ini_filename os.chdir(os.path.dirname(ini_filename)) inifile = linuxcnc.ini(ini_filename) gremlin.Gremlin.__init__(self, inifile) self._reload_filename = None self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.gstat.connect('reload-display', self.reloadfile) self.init_glcanondraw( trajcoordinates=self.inifile.find('TRAJ', 'COORDINATES'), kinsmodule=self.inifile.find('KINS', 'KINEMATICS')) self.show()
def __init__(self, *a, **kw): gobject.GObject.__init__(self) ini_filename = os.environ.get('INI_FILE_NAME') if ini_filename is None: ini_filename = get_linuxcnc_ini_file() if ini_filename is not None: os.putenv('INI_FILE_NAME',ini_filename) os.environ['INI_FILE_NAME'] = ini_filename os.chdir(os.path.dirname(ini_filename)) inifile = linuxcnc.ini(ini_filename) gremlin.Gremlin.__init__(self, inifile) self._reload_filename = None self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.gstat.connect('reload-display', self.reloadfile) self.init_glcanondraw( trajcoordinates=self.inifile.find('TRAJ','COORDINATES'), kinsmodule=self.inifile.find('KINS','KINEMATICS')) self.show()
class Combi_DRO(Gtk.VBox): ''' Combi_DRO will display an linuxcnc DRO with all three types at ones Combi_DRO = Combi_DRO(joint_number) joint_number is an integer in the range from 0 to 8 where 0 = X, 1 = Y, 2 = Z, etc. ''' __gtype_name__ = 'Combi_DRO' __gproperties__ = { 'joint_number': (GObject.TYPE_INT, 'Joint Number', '0:X 1:Y 2:Z etc', 0, 8, 0, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'actual': (GObject.TYPE_BOOLEAN, 'Actual Position', 'Display Actual or Commanded Position', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'metric_units': (GObject.TYPE_BOOLEAN, 'Display in metric units', 'Display in metric or not', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'auto_units': (GObject.TYPE_BOOLEAN, 'Change units according gcode', 'Units will toggle between metric and imperial according to gcode.', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'diameter': (GObject.TYPE_BOOLEAN, 'Diameter Adjustment', 'Display Position As Diameter', False, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'mm_text_template': (GObject.TYPE_STRING, 'Text template for Metric Units', 'Text template to display. Python formatting may be used for one variable', "%10.3f", GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'imperial_text_template': (GObject.TYPE_STRING, 'Text template for Imperial Units', 'Text template to display. Python formatting may be used for one variable', "%9.4f", GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'homed_color': (Gdk.RGBA.__gtype__, 'homed color', 'Sets the color of the display when the axis is homed', GObject.ParamFlags.READWRITE), 'unhomed_color': (Gdk.RGBA.__gtype__, 'unhomed color', 'Sets the color of the display when the axis is not homed', GObject.ParamFlags.READWRITE), 'abs_color': (Gdk.RGBA.__gtype__, 'Absolute color', 'Sets the color of the display when absolute coordinates are used', GObject.ParamFlags.READWRITE), 'rel_color': (Gdk.RGBA.__gtype__, 'Relative color', 'Sets the color of the display when relative coordinates are used', GObject.ParamFlags.READWRITE), 'dtg_color': (Gdk.RGBA.__gtype__, 'DTG color', 'Sets the color of the display when dtg coordinates are used', GObject.ParamFlags.READWRITE), 'font_size': (GObject.TYPE_INT, 'Font Size', 'The font size of the big numbers, the small ones will be 2.5 times smaller', 8, 96, 25, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'toggle_readout': (GObject.TYPE_BOOLEAN, 'Enable toggling readout with click', 'The DRO will toggle between Absolute , Relativ and DTG with each mouse click.', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'cycle_time': (GObject.TYPE_INT, 'Cycle Time', 'Time, in milliseconds, that display will sleep between polls', 100, 1000, 150, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'clicked': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING, GObject.TYPE_PYOBJECT)), 'units_changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN, )), 'system_changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING, )), 'axis_clicked': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING, )), 'exit': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ()), } # Init the class def __init__(self, joint_number=0): super(Combi_DRO, self).__init__() # we have to distinguish this, as we use the joints number to check homing # and we do need the axis to check for the positions # this is needed if non trivial kinematics are used or just a lathe, # as the lathe has only two joints, but Z will be the third value in position feedback self.axis_no = self.joint_number = joint_number # get the necessary connections to linuxcnc self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.gstat = GStat() # set some default values' self._ORDER = ["Rel", "Abs", "DTG"] self.system = "Rel" self.homed = False self.homed_color = "#00FF00" self.unhomed_color = "#FF0000" self.abs_color = "#0000FF" self.rel_color = "#000000" self.dtg_color = "#FFFF00" self.mm_text_template = "%10.3f" self.imperial_text_template = "%9.4f" self.font_size = 25 self.metric_units = True self.machine_units = _MM self.unit_convert = 1 self._auto_units = True self.toggle_readout = True self.cycle_time = 150 self.diameter = False self.actual = True self.widgets = {} # will hold all our widgets we need to style # Make the GUI and connect signals self.css = Gtk.CssProvider() self.css_text = """ .background {background-color: #000000;} .labelcolor {color: #FF0000;} .size_big {font-size: 25px;font-weight: bold;} .size_small {font-size: 10px;font-weight: bold;} """ self.css = Gtk.CssProvider() self.css.load_from_data(bytes(self.css_text, 'utf-8')) eventbox = Gtk.EventBox() eventbox.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) eventbox.get_style_context().add_class('background') self.add(eventbox) vbox_main = Gtk.VBox(homogeneous=False, spacing=0) eventbox.add(vbox_main) hbox_up = Gtk.HBox(homogeneous=False, spacing=5) vbox_main.pack_start(hbox_up, True, True, 0) self.widgets["eventbox"] = eventbox lbl_axisletter = Gtk.Label(label=_AXISLETTERS[self.axis_no]) lbl_axisletter.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_axisletter.get_style_context().add_class('background') lbl_axisletter.get_style_context().add_class('labelcolor') lbl_axisletter.get_style_context().add_class('size_big') hbox_up.pack_start(lbl_axisletter, False, False, 0) self.widgets["lbl_axisletter"] = lbl_axisletter vbox_ref_type = Gtk.VBox(homogeneous=False, spacing=0) hbox_up.pack_start(vbox_ref_type, False, False, 0) # This label is needed to press the main index (rel,Abs;Dtg) to the upper part lbl_space = Gtk.Label(label="") vbox_ref_type.pack_start(lbl_space, True, True, 0) lbl_sys_main = Gtk.Label(label=self.system) lbl_sys_main.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_sys_main.get_style_context().add_class('background') lbl_sys_main.get_style_context().add_class('labelcolor') lbl_sys_main.get_style_context().add_class("size_small") vbox_ref_type.pack_start(lbl_sys_main, False, False, 0) self.widgets["lbl_sys_main"] = lbl_sys_main main_dro = Gtk.Label(label="9999.999") main_dro.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) main_dro.get_style_context().add_class('background') main_dro.get_style_context().add_class('labelcolor') main_dro.get_style_context().add_class("size_big") main_dro.set_xalign(1.0) hbox_up.pack_start(main_dro, True, True, 0) self.widgets["main_dro"] = main_dro hbox_down = Gtk.HBox(homogeneous=True, spacing=5) vbox_main.pack_start(hbox_down, False, False, 0) lbl_sys_left = Gtk.Label(label="Abs") lbl_sys_left.set_xalign(0.0) lbl_sys_left.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_sys_left.get_style_context().add_class('background') lbl_sys_left.get_style_context().add_class('labelcolor') lbl_sys_left.get_style_context().add_class('size_small') hbox_down.pack_start(lbl_sys_left, True, True, 0) self.widgets["lbl_sys_left"] = lbl_sys_left dro_left = Gtk.Label(label="-11.111") dro_left.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) dro_left.get_style_context().add_class('background') dro_left.get_style_context().add_class('labelcolor') dro_left.get_style_context().add_class('size_small') dro_left.set_xalign(1.0) hbox_down.pack_start(dro_left, True, True, 0) self.widgets["dro_left"] = dro_left lbl_sys_right = Gtk.Label(label="DTG") lbl_sys_right.set_xalign(0.0) lbl_sys_right.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_sys_right.get_style_context().add_class('background') lbl_sys_right.get_style_context().add_class('labelcolor') lbl_sys_right.get_style_context().add_class('size_small') hbox_down.pack_start(lbl_sys_right, False, False, 0) self.widgets["lbl_sys_right"] = lbl_sys_right dro_right = Gtk.Label(label="22.222") dro_right.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) dro_right.get_style_context().add_class('background') dro_right.get_style_context().add_class('labelcolor') dro_right.get_style_context().add_class('size_small') dro_right.set_xalign(1.0) hbox_down.pack_start(dro_right, True, True, 0) self.widgets["dro_right"] = dro_right eventbox.connect("button_press_event", self._on_eventbox_clicked) self.show_all() self.gstat.connect('not-all-homed', self._not_all_homed) self.gstat.connect('all-homed', self._all_homed) self.gstat.connect('homed', self._homed) self.gstat.connect('current-position', self._position) # This try is only needed because while working with glade # linuxcnc may not be working try: self.inifile = self.linuxcnc.ini(INIPATH) # check the ini file if UNITS are set to mm" # first check the global settings units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: # else then the X axis units units = self.inifile.find("AXIS_0", "UNITS") except: units = "inch" if units == "mm" or units == "metric" or units == "1.0": self.machine_units = _MM else: self.machine_units = _INCH # if the eventbox has been clicked, we like to toggle the DRO's # or just emit a signal to allow GUI to do what ever they want with that # signal- gmoccapy uses this signal to open the touch off dialog def _on_eventbox_clicked(self, widget, event): if event.x <= self.widgets["lbl_axisletter"].get_allocation( ).width + self.widgets["lbl_sys_main"].get_allocation().width: self.emit('axis_clicked', self.widgets["lbl_axisletter"].get_text().lower()) #self.set_style("labelcolor", "#00FF00") else: if not self.toggle_readout: return self.toogle_readout() # Get propertys def do_get_property(self, property): name = property.name.replace('-', '_') if name in list(self.__gproperties.keys()): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) def convert_color(self, color): colortuple = ((int(color.red * 255.0), int(color.green * 255.0), int(color.blue * 255.0))) return ('#' + ''.join(f'{i:02X}' for i in colortuple)) # Set propertys def do_set_property(self, property, value): try: name = property.name.replace('-', '_') if name in list(self.__gproperties.keys()): # setattr(self, name, value) # self.queue_draw() if name in ('mm_text_template', 'imperial_text_template'): try: v = value % 0.0 except Exception as e: print("Invalid format string '%s': %s" % (value, e)) return False if name == "homed_color": self.homed_color = self.convert_color(value) if self.homed: self.set_style("labelcolor", self.homed_color) else: self.set_style("labelcolor", self.unhomed_color) if name == "unhomed_color": self.unhomed_color = self.convert_color(value) if self.homed: self.set_style("labelcolor", self.homed_color) else: self.set_style("labelcolor", self.unhomed_color) if name == "abs_color": self.abs_color = self.convert_color(value) self.toggle_readout(True) if name == "rel_color": self.rel_color = self.convert_color(value) self.toggle_readout(True) if name == "dtg_color": self.dtg_color = self.convert_color(value) self.toggle_readout(True) if name == "auto_units": self._auto_units = value self._set_labels() if name == "joint_number": self.axis_no = self.joint = value self.change_axisletter(_AXISLETTERS[self.axis_no]) if name == "font_size": self.font_size = int(value) self.set_style("size", self.font_size) if name == "toggle_readout": self.toggle_readout = value if name == "cycle_time": self.cycle_time = value if name in ('metric_units', 'actual', 'diameter'): setattr(self, name, value) self.queue_draw() else: raise AttributeError('unknown property %s' % property.name) except: pass # get the actual coordinate system to display it on the DRO def _get_current_system(self): gcode = self.status.gcodes[1:] for code in gcode: if code >= 540 and code <= 590: return "G%s" % int((code / 10)) elif code > 590 and code <= 593: return "G%s" % int((code / 10.0)) return "Rel" # Get the units used according to gcode def _get_current_units(self): gcode = self.status.gcodes[1:] for code in gcode: if code >= 200 and code <= 210: return (code / 10) return False # update the labels def _set_labels(self): if self._ORDER[0] == "Rel": self.widgets["lbl_sys_main"].set_text(self._get_current_system()) else: self.widgets["lbl_sys_main"].set_text(self._ORDER[0]) if self._ORDER[1] == "Rel": self.widgets["lbl_sys_left"].set_text(self._get_current_system()) else: self.widgets["lbl_sys_left"].set_text(self._ORDER[1]) if self._ORDER[2] == "Rel": self.widgets["lbl_sys_right"].set_text(self._get_current_system()) else: self.widgets["lbl_sys_right"].set_text(self._ORDER[2]) self.system = self._get_current_system() def set_style(self, property, Data): # self.css_text = """ # .background {background-color: black;} # .labelcolor {color: red;} # .size_big {font-size: 25px;font-weight: bold;} # .size_small {font-size: 10px;font-weight: bold;} # """ if property == "background": for widget in self.widgets: self.widgets[widget].get_style_context().remove_class( 'background') replacement_string = ".background {background-color: " + Data + ";}" self.css_text = re.sub(r'[.][b][a][c][k][g][r][o][u][n][d].*', replacement_string, self.css_text, re.IGNORECASE) elif property == "labelcolor": for widget in self.widgets: self.widgets[widget].get_style_context().remove_class( 'labelcolor') replacement_string = ".labelcolor {color: " + Data + ";}" self.css_text = re.sub(r'[.][l][a][b][e][l][c][o][l][o][r].*', replacement_string, self.css_text, re.IGNORECASE) elif property == "size": for widget in self.widgets: self.widgets[widget].get_style_context().remove_class( 'size_big') self.widgets[widget].get_style_context().remove_class( 'size_small') replacement_string = ".size_big {font-size: " + str( Data) + "px;font-weight: bold;}" self.css_text = re.sub(r'[.][s][i][z][e][_][b][i][g].*', replacement_string, self.css_text, re.IGNORECASE) replacement_string = ".size_small {font-size: " + str( int(Data / 2.5)) + "px;font-weight: bold;}" self.css_text = re.sub(r'[.][s][i][z][e][_][s][m][a][l][l].*', replacement_string, self.css_text, re.IGNORECASE) else: print("Got unknown property in <<set_style>>") return self.css.load_from_data(bytes(self.css_text, 'utf-8')) for widget in self.widgets: self.widgets[widget].get_style_context().add_class('background') self.widgets[widget].get_style_context().add_class('labelcolor') if widget in ("lbl_axisletter", "main_dro"): self.widgets[widget].get_style_context().add_class('size_big') else: self.widgets[widget].get_style_context().add_class( 'size_small') self.queue_draw() def _position(self, object, p, rel_p, dtg, joint_actual_position): # object = hal_glib Object # p = self.stat.actual_position # rel_p = relative position # dtg = distance to go # joint_actual_position = joint positions, not needed here try: dtg = dtg[self.axis_no] abs_pos = p[self.axis_no] rel_pos = rel_p[self.axis_no] except: return if self._ORDER == ["Rel", "Abs", "DTG"]: main, left, right = rel_pos, abs_pos, dtg if self._ORDER == ["DTG", "Rel", "Abs"]: main, left, right = dtg, rel_pos, abs_pos if self._ORDER == ["Abs", "DTG", "Rel"]: main, left, right = abs_pos, dtg, rel_pos if self.metric_units: tmpl = lambda s: self.mm_text_template % s else: tmpl = lambda s: self.imperial_text_template % s if self.diameter: scale = 2.0 else: scale = 1.0 main_dro = tmpl(main * scale) left_dro = tmpl(left * scale) right_dro = tmpl(right * scale) self.widgets["main_dro"].set_label(main_dro) self.widgets["dro_left"].set_label(left_dro) self.widgets["dro_right"].set_label(right_dro) def _not_all_homed(self, widget, data=None): if self.status.kinematics_type == linuxcnc.KINEMATICS_IDENTITY: self.status.poll() self.homed = self.status.homed[self.joint_no] else: self.homed = False if self.homed: self.set_style("labelcolor", self.homed_color) else: self.set_style("labelcolor", self.unhomed_color) def _all_homed(self, widget, data=None): if self.status.kinematics_type == linuxcnc.KINEMATICS_IDENTITY: return if not self.homed: self.homed = True self.set_style("labelcolor", self.homed_color) def _homed(self, widget, data=None): if self.status.kinematics_type != linuxcnc.KINEMATICS_IDENTITY: return else: self.status.poll() self.homed = self.status.homed[self.joint_no] self.set_style("labelcolor", self.homed_color) # sets the DRO explicitly to inch or mm # attentions auto_units also takes effect on that! def set_to_inch(self, state): ''' sets the DRO to show imperial units Combi_DRO.set_to_inch(state) state = boolean (true or False) ''' if state: self.metric_units = False else: self.metric_units = True # If auto_units is true, the DRO will change according to the # active gcode (G20 / G21) def set_auto_units(self, state): ''' if True the DRO will change units according to active gcode (G20 / G21) Combi_DRO.set_auto_units(state) state = boolean (true or False) ''' self._auto_units = state # Set the axis to diameter mode, the DRO value will be # multiplied by 2 def set_to_diameter(self, state): ''' if True the DRO will show the diameter not the radius, specially needed for lathes the DRO value will be multiplied by 2 Combi_DRO.set_to_diameter(state) state = boolean (true or False) ''' self.diameter = state # this will toggle the DRO around, mainly used to maintain all DRO # at the same state, because a click on one will only change that DRO # This can be used to change also the others def toogle_readout(self, Data=None): ''' toggles the order of the DRO in the widget Combi_DRO.toggle_readout() ''' self._ORDER = [self._ORDER[2], self._ORDER[0], self._ORDER[1]] if self._ORDER[0] == "Abs": bg_color = self.abs_color elif self._ORDER[0] == "DTG": bg_color = self.dtg_color else: bg_color = self.rel_color self.set_style("background", bg_color) # if Data is True, we only updated the colors of the background # so we won#t emit a click event if Data: return self._set_labels() self.emit("clicked", self.joint_number, self._ORDER) # You can change the automatic given axisletter using this function # i.e. to use an axis as R or D insteadt of X on a lathe def change_axisletter(self, letter): ''' changes the automatically given axis-letter very useful to change an lathe DRO from X to R or D Combi_DRO.change_axis-letter(letter) letter = string ''' self.widgets["lbl_axisletter"].set_text(letter) def set_joint_no(self, joint): ''' changes the joint, not the joint number. This is handy for special cases, like Gantry configs, i.e. XYYZ, where joint 0 = X, joint 1 = Y1 joint 2 = Y2 and joint 3 = Z, so the Z axis can be set to joint_number 2 giving the axis letter Z and joint 3 being in this case the corresponding joint, joint 3 instead of 2 ''' self.joint_no = joint def set_axis(self, axis): ''' changes the axis, not the joint number. This is handy for special cases, like Lathe configs, i.e. XZ, where joint 0 = X, joint 1 = Z so the Z axis must be set to joint_number 1 for homing, but we need the axis letter Z to give the correct position feedback ''' self.axis_no = "xyzabcuvws".index(axis.lower()) # returns the order of the DRO, mainly used to maintain them consistent # the order will also be transmitted with the clicked signal def get_order(self): ''' returns the order of the DRO in the widget mainly used to maintain them consistent the order will also be transmitted with the clicked signal Combi_DRO.get_order() returns a list containing the order ''' return self._ORDER # sets the order of the DRO, mainly used to maintain them consistent def set_order(self, order): ''' sets the order of the DRO, mainly used to maintain them consistent Combi_DRO.set_order(order) order = list object, must be one of ["Rel", "Abs", "DTG"] ["DTG", "Rel", "Abs"] ["Abs", "DTG", "Rel"] ''' self._ORDER = order self._set_labels() self.toogle_readout(Data=True) # This will return the position information of all three DRO # it will be in the order Abs, Rel, DTG def get_position(self): ''' returns the positions of the DRO Combi_DRO.get_position() returns the position of the DRO as a list of floats the order is independent of the order shown on the DRO and will be givven as [Absolute , relative , DTG] Absolute = the machine coordinates, depends on the actual property will give actual or commanded position Relative = will be the coordinates of the actual coordinate system DTG = the distance to go, will mosltly be 0, as this function should not be used while the machine is moving, because of time delays ''' positions = self._position() if self._ORDER == ["Rel", "Abs", "DTG"]: return positions[1], positions[0], positions[2] if self._ORDER == ["DTG", "Rel", "Abs"]: return positions[2], positions[1], positions[0] if self._ORDER == ["Abs", "DTG", "Rel"]: return positions[0], positions[2], positions[1]
def __init__(self, joint_number=0): super(Combi_DRO, self).__init__() # we have to distinguish this, as we use the joints number to check homing # and we do need the axis to check for the positions # this is needed if non trivial kinematics are used or just a lathe, # as the lathe has only two joints, but Z will be the third value in position feedback self.axis_no = self.joint_number = joint_number # get the necessary connections to linuxcnc self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.gstat = GStat() # set some default values' self._ORDER = ["Rel", "Abs", "DTG"] self.system = "Rel" self.homed = False self.homed_color = "#00FF00" self.unhomed_color = "#FF0000" self.abs_color = "#0000FF" self.rel_color = "#000000" self.dtg_color = "#FFFF00" self.mm_text_template = "%10.3f" self.imperial_text_template = "%9.4f" self.font_size = 25 self.metric_units = True self.machine_units = _MM self.unit_convert = 1 self._auto_units = True self.toggle_readout = True self.cycle_time = 150 self.diameter = False self.actual = True self.widgets = {} # will hold all our widgets we need to style # Make the GUI and connect signals self.css = Gtk.CssProvider() self.css_text = """ .background {background-color: #000000;} .labelcolor {color: #FF0000;} .size_big {font-size: 25px;font-weight: bold;} .size_small {font-size: 10px;font-weight: bold;} """ self.css = Gtk.CssProvider() self.css.load_from_data(bytes(self.css_text, 'utf-8')) eventbox = Gtk.EventBox() eventbox.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) eventbox.get_style_context().add_class('background') self.add(eventbox) vbox_main = Gtk.VBox(homogeneous=False, spacing=0) eventbox.add(vbox_main) hbox_up = Gtk.HBox(homogeneous=False, spacing=5) vbox_main.pack_start(hbox_up, True, True, 0) self.widgets["eventbox"] = eventbox lbl_axisletter = Gtk.Label(label=_AXISLETTERS[self.axis_no]) lbl_axisletter.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_axisletter.get_style_context().add_class('background') lbl_axisletter.get_style_context().add_class('labelcolor') lbl_axisletter.get_style_context().add_class('size_big') hbox_up.pack_start(lbl_axisletter, False, False, 0) self.widgets["lbl_axisletter"] = lbl_axisletter vbox_ref_type = Gtk.VBox(homogeneous=False, spacing=0) hbox_up.pack_start(vbox_ref_type, False, False, 0) # This label is needed to press the main index (rel,Abs;Dtg) to the upper part lbl_space = Gtk.Label(label="") vbox_ref_type.pack_start(lbl_space, True, True, 0) lbl_sys_main = Gtk.Label(label=self.system) lbl_sys_main.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_sys_main.get_style_context().add_class('background') lbl_sys_main.get_style_context().add_class('labelcolor') lbl_sys_main.get_style_context().add_class("size_small") vbox_ref_type.pack_start(lbl_sys_main, False, False, 0) self.widgets["lbl_sys_main"] = lbl_sys_main main_dro = Gtk.Label(label="9999.999") main_dro.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) main_dro.get_style_context().add_class('background') main_dro.get_style_context().add_class('labelcolor') main_dro.get_style_context().add_class("size_big") main_dro.set_xalign(1.0) hbox_up.pack_start(main_dro, True, True, 0) self.widgets["main_dro"] = main_dro hbox_down = Gtk.HBox(homogeneous=True, spacing=5) vbox_main.pack_start(hbox_down, False, False, 0) lbl_sys_left = Gtk.Label(label="Abs") lbl_sys_left.set_xalign(0.0) lbl_sys_left.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_sys_left.get_style_context().add_class('background') lbl_sys_left.get_style_context().add_class('labelcolor') lbl_sys_left.get_style_context().add_class('size_small') hbox_down.pack_start(lbl_sys_left, True, True, 0) self.widgets["lbl_sys_left"] = lbl_sys_left dro_left = Gtk.Label(label="-11.111") dro_left.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) dro_left.get_style_context().add_class('background') dro_left.get_style_context().add_class('labelcolor') dro_left.get_style_context().add_class('size_small') dro_left.set_xalign(1.0) hbox_down.pack_start(dro_left, True, True, 0) self.widgets["dro_left"] = dro_left lbl_sys_right = Gtk.Label(label="DTG") lbl_sys_right.set_xalign(0.0) lbl_sys_right.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) lbl_sys_right.get_style_context().add_class('background') lbl_sys_right.get_style_context().add_class('labelcolor') lbl_sys_right.get_style_context().add_class('size_small') hbox_down.pack_start(lbl_sys_right, False, False, 0) self.widgets["lbl_sys_right"] = lbl_sys_right dro_right = Gtk.Label(label="22.222") dro_right.get_style_context().add_provider( self.css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) dro_right.get_style_context().add_class('background') dro_right.get_style_context().add_class('labelcolor') dro_right.get_style_context().add_class('size_small') dro_right.set_xalign(1.0) hbox_down.pack_start(dro_right, True, True, 0) self.widgets["dro_right"] = dro_right eventbox.connect("button_press_event", self._on_eventbox_clicked) self.show_all() self.gstat.connect('not-all-homed', self._not_all_homed) self.gstat.connect('all-homed', self._all_homed) self.gstat.connect('homed', self._homed) self.gstat.connect('current-position', self._position) # This try is only needed because while working with glade # linuxcnc may not be working try: self.inifile = self.linuxcnc.ini(INIPATH) # check the ini file if UNITS are set to mm" # first check the global settings units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: # else then the X axis units units = self.inifile.find("AXIS_0", "UNITS") except: units = "inch" if units == "mm" or units == "metric" or units == "1.0": self.machine_units = _MM else: self.machine_units = _INCH
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gsignals__ = { 'line-clicked': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_INT, )), 'gcode_error': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING, )), } __gproperties__ = { 'view': (GObject.TYPE_STRING, 'View type', 'Default view: p, x, y, y2, z, z2', 'p', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'enable_dro': (GObject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'metric_units': (GObject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'use_relative': (GObject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'use_commanded': (GObject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_extents_option': (GObject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_limits': (GObject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_live_plot': (GObject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_velocity': (GObject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_program': (GObject.TYPE_BOOLEAN, 'Show program', 'Show program', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_rapids': (GObject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_tool': (GObject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_dtg': (GObject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'show_lathe_radius': (GObject.TYPE_BOOLEAN, 'Show Lathe Radius', 'Show X axis in Radius', False, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'grid_size': (GObject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'use_joints_mode': (GObject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'use_default_controls': (GObject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'mouse_btn_mode': (GObject.TYPE_INT, 'Mouse Button Mode', ('Mousebutton assignment, l means left, m middle, r right \n' '0 = default: l-rotate, m-move, r-zoom \n' '1 = l-zoom, m-move, r-rotate\n' '2 = l-move, m-rotate, r-zoom\n' '3 = l-zoom, m-rotate, r-move\n' '4 = l-move, m-zoom, r-rotate\n' '5 = l-rotate, m-zoom, r-move\n' '6 = l-move, m-zoom, r-zoom'), 0, 6, 0, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): GObject.GObject.__init__(self) ini_filename = os.environ.get('INI_FILE_NAME') if ini_filename is None: ini_filename = get_linuxcnc_ini_file() if ini_filename is not None: os.putenv('INI_FILE_NAME', ini_filename) os.environ['INI_FILE_NAME'] = ini_filename os.chdir(os.path.dirname(ini_filename)) inifile = linuxcnc.ini(ini_filename) gremlin.Gremlin.__init__(self, inifile) self._reload_filename = None self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.gstat.connect('reload-display', self.reloadfile) self.init_glcanondraw( trajcoordinates=self.inifile.find('TRAJ', 'COORDINATES'), kinsmodule=self.inifile.find('KINS', 'KINEMATICS')) self.show() def reloadfile(self, w): try: self.fileloaded(None, self._reload_filename) except: pass def fileloaded(self, w, f): self._reload_filename = f try: self._load(f) except AttributeError as detail: #AttributeError: 'NoneType' object has no attribute 'gl_end' print('hal_gremlin: continuing after', detail) def do_get_property(self, property): name = property.name.replace('-', '_') if name == 'view': return self.current_view elif name in list(self.__gproperties.keys()): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) def do_set_property(self, property, value): name = property.name.replace('-', '_') if name == 'view': view = value.lower() if self.lathe_option: if view not in ['p', 'y', 'y2']: return False elif view not in ['p', 'x', 'y', 'z', 'z2']: return False self.current_view = view if self.initialised: self.set_current_view() elif name == 'enable_dro': self.enable_dro = value elif name == 'metric_units': self.metric_units = value elif name in list(self.__gproperties.keys()): setattr(self, name, value) else: raise AttributeError('unknown property %s' % property.name) self.queue_draw() return True # This overrides glcannon.py method so we can change the DRO def dro_format(self, s, spd, dtg, limit, homed, positions, axisdtg, g5x_offset, g92_offset, tlo_offset): if self.metric_units: format = "% 6s:% 9.3f" if self.show_dtg: droformat = " " + format + " DTG %1s:% 9.3f" else: droformat = " " + format offsetformat = "% 5s %1s:% 9.3f G92 %1s:% 9.3f" rotformat = "% 5s %1s:% 9.3f" else: format = "% 6s:% 9.4f" if self.show_dtg: droformat = " " + format + " DTG %1s:% 9.4f" else: droformat = " " + format offsetformat = "% 5s %1s:% 9.4f G92 %1s:% 9.4f" rotformat = "% 5s %1s:% 9.4f" diaformat = " " + format posstrs = [] droposstrs = [] for i in range(9): a = "XYZABCUVW"[i] if s.axis_mask & (1 << i): posstrs.append(format % (a, positions[i])) if self.show_dtg: droposstrs.append(droformat % (a, positions[i], a, axisdtg[i])) else: droposstrs.append(droformat % (a, positions[i])) droposstrs.append("") for i in range(9): index = s.g5x_index if index < 7: label = "G5%d" % (index + 3) else: label = "G59.%d" % (index - 6) a = "XYZABCUVW"[i] if s.axis_mask & (1 << i): droposstrs.append(offsetformat % (label, a, g5x_offset[i], a, g92_offset[i])) droposstrs.append(rotformat % (label, 'R', s.rotation_xy)) droposstrs.append("") for i in range(9): a = "XYZABCUVW"[i] if s.axis_mask & (1 << i): droposstrs.append(rotformat % ("TLO", a, tlo_offset[i])) # if its a lathe only show radius or diameter as per property if self.is_lathe(): posstrs[0] = "" if self.show_lathe_radius: posstrs.insert(1, format % ("Rad", positions[0])) else: posstrs.insert(1, format % ("Dia", positions[0] * 2.0)) droposstrs[0] = "" if self.show_dtg: if self.show_lathe_radius: droposstrs.insert( 1, droformat % ("Rad", positions[0], "R", axisdtg[0])) else: droposstrs.insert( 1, droformat % ("Dia", positions[0] * 2.0, "D", axisdtg[0] * 2.0)) else: if self.show_lathe_radius: droposstrs.insert(1, droformat % ("Rad", positions[0])) else: droposstrs.insert(1, diaformat % ("Dia", positions[0] * 2.0)) if self.show_velocity: posstrs.append(format % ("Vel", spd)) pos = 0 for i in range(9): if s.axis_mask & (1 << i): pos += 1 if self.is_lathe: pos += 1 droposstrs.insert(pos, " " + format % ("Vel", spd)) if self.show_dtg: posstrs.append(format % ("DTG", dtg)) return limit, homed, posstrs, droposstrs # Override gremlin's / glcannon.py function so we can emit a GObject signal def update_highlight_variable(self, line): self.highlight_line = line if line == None: line = -1 self.emit('line-clicked', line) def realize(self, widget): gremlin.Gremlin.realize(self, widget) @rs274.glcanon.with_context def _load(self, filename): return self.load(filename) def report_gcode_error(self, result, seq, filename): error_str = gcode.strerror(result) errortext = "G-Code error in " + os.path.basename(filename) + "\n" + "Near line " \ + str(seq) + " of\n" + filename + "\n" + error_str + "\n" print(errortext) self.emit("gcode-error", errortext)
class EMC_MDIHistory(gtk.VBox, _EMC_ActionBase): __gtype_name__ = 'EMC_MDIHistory' def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) self.no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Command") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on())) self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) # this time lambda with two parameters, as not all homed will send also the unhomed joints self.gstat.connect('not-all-homed', lambda w,uj: self.set_sensitive(self.no_home_required) ) self.reload() self.show_all() def reload(self): self.model.clear() try: fp = open(self.filename) except: return lines = map(str.strip, fp.readlines()) fp.close() lines = filter(bool, lines) for l in lines: self.model.append((l,)) path = (len(lines)-1,) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') def submit(self, *a): cmd = self.entry.get_text() if cmd == 'HALMETER': self.load_halmeter() return elif cmd == 'STATUS': self.load_status() return elif cmd == 'HALSHOW': self.load_halshow() return if not cmd: return ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI) try: fp = open(self.filename, 'a') fp.write(cmd + "\n") fp.close() except: pass self.linuxcnc.mdi(cmd) last = self.model.append((cmd,)) path = self.model.get_path(last) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') self.entry.grab_focus() def select(self, w): self.entry.set_text('') def on_key_press_event(self,w,event): idx = w.get_cursor()[0] if idx is None: return True if gtk.gdk.keyval_name(event.keyval) == 'Return': self.entry.set_text(self.model[idx][0]) self.entry.grab_focus() return True def on_button_press_event(self,w,event): idx = w.get_cursor()[0] if idx is None: return True self.entry.set_text(self.model[idx][0]) def load_halmeter(self): p = os.popen("halmeter &") def load_status(self): p = os.popen("linuxcnctop > /dev/null &","w") def load_halshow(self): try: p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH)) except: self.entry.set_text('ERROR loading halshow')
class MacroSelect(gtk.VBox, _EMC_ActionBase): __gtype_name__ = 'MacroSelect' __gsignals__ = { 'macro-submitted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,gobject.TYPE_STRING,)), } def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. try: inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) macros = self.inifile.findall("MACROS", "MACRO") sub_path = self.inifile.find("RS274NGC", "SUBROUTINE_PATH")or '~/linuxcnc/nc_files/macros' except: no_home_required = 1 macros = None sub_path = '~/linuxcnc/nc_files/macros' #path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.foldername = os.path.expanduser(sub_path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Macro Commands") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on() and ( self.is_all_homed() or no_home_required ) )) self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) self.reload() self.show_all() def reload(self): self.model.clear() files = [] try: for f in os.listdir(self.foldername): if f.endswith('.ngc'): with open(os.path.join(self.foldername, f), 'r') as temp: first_line = temp.readline().strip() print first_line if 'MACROCOMMAND' in first_line: files.append(first_line.strip('; MACROCOMMAND=')) except: pass lines = filter(bool, files) for l in lines: self.model.append((l,)) path = (len(lines)-1,) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') def submit(self, *a): cmd = self.entry.get_text() if cmd == 'HALMETER': self.load_halmeter() return elif cmd == 'STATUS': self.load_status() return elif cmd == 'HALSHOW': self.load_halshow() return if not cmd: return #ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI) name = cmd.split() path = self.foldername+ "/" + name[0] + ".ngc" self.emit('macro-submitted',path,cmd) #self.linuxcnc.mdi(cmd) self.entry.set_text('') self.entry.grab_focus() def select(self, w): self.entry.set_text('') def on_key_press_event(self,w,event): idx = w.get_cursor()[0] if idx is None: return True if gtk.gdk.keyval_name(event.keyval) == 'Return': self.entry.set_text(self.model[idx][0]) self.entry.grab_focus() return True def on_button_press_event(self,w,event): idx = w.get_cursor()[0] if idx is None: return True self.entry.set_text(self.model[idx][0]) def load_halmeter(self): p = os.popen("halmeter &") def load_status(self): p = os.popen("linuxcnctop > /dev/null &","w") def load_halshow(self): try: p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH)) except: self.entry.set_text('ERROR loading halshow')
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gproperties__ = { 'view': (gobject.TYPE_STRING, 'View type', 'Default view: p, x, y, y2, z, z2', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro': (gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units': (gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative': (gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded': (gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option': (gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits': (gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot': (gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity': (gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program': (gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids': (gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool': (gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg': (gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_lathe_radius': (gobject.TYPE_BOOLEAN, 'Show Lathe Radius', 'Show X axis in Radius', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'grid_size': (gobject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode': (gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_default_controls': (gobject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self.gstat = GStat() self.gstat.connect('file-loaded', lambda w, f: self._load(f)) self.show() def do_get_property(self, property): name = property.name.replace('-', '_') if name == 'view': return self.current_view elif name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) def do_set_property(self, property, value): name = property.name.replace('-', '_') if name == 'view': view = value.lower() if self.lathe_option: if view not in ['p', 'y', 'y2']: return False elif view not in ['p', 'x', 'y', 'z', 'z2']: return False self.current_view = view if self.initialised: self.set_current_view() elif name == 'enable_dro': self.enable_dro = value elif name == 'metric_units': self.metric_units = value elif name in self.__gproperties.keys(): setattr(self, name, value) else: raise AttributeError('unknown property %s' % property.name) self.queue_draw() return True # This overrides glcannon.py method so we can change the DRO def dro_format(self, s, spd, dtg, limit, homed, positions, axisdtg, g5x_offset, g92_offset, tlo_offset): if not self.enable_dro: return limit, homed, [''], [''] if self.metric_units: format = "% 6s:% 9.3f" if self.show_dtg: droformat = " " + format + " DTG %1s:% 9.3f" else: droformat = " " + format offsetformat = "% 5s %1s:% 9.3f G92 %1s:% 9.3f" rotformat = "% 5s %1s:% 9.3f" else: format = "% 6s:% 9.4f" if self.show_dtg: droformat = " " + format + " DTG %1s:% 9.4f" else: droformat = " " + format offsetformat = "% 5s %1s:% 9.4f G92 %1s:% 9.4f" rotformat = "% 5s %1s:% 9.4f" diaformat = " " + format posstrs = [] droposstrs = [] for i in range(9): a = "XYZABCUVW"[i] if s.axis_mask & (1 << i): posstrs.append(format % (a, positions[i])) if self.show_dtg: droposstrs.append(droformat % (a, positions[i], a, axisdtg[i])) else: droposstrs.append(droformat % (a, positions[i])) droposstrs.append("") for i in range(9): index = s.g5x_index if index < 7: label = "G5%d" % (index + 3) else: label = "G59.%d" % (index - 6) a = "XYZABCUVW"[i] if s.axis_mask & (1 << i): droposstrs.append(offsetformat % (label, a, g5x_offset[i], a, g92_offset[i])) droposstrs.append(rotformat % (label, 'R', s.rotation_xy)) droposstrs.append("") for i in range(9): a = "XYZABCUVW"[i] if s.axis_mask & (1 << i): droposstrs.append(rotformat % ("TLO", a, tlo_offset[i])) # if its a lathe only show radius or diameter as per property # we have to adjust the homing icon to line up: if self.is_lathe(): if homed[0]: homed.pop(0) homed.pop(0) homed.insert(0, 1) homed.insert(0, 0) posstrs[0] = "" if self.show_lathe_radius: posstrs.insert(1, format % ("Rad", positions[0])) else: posstrs.insert(1, format % ("Dia", positions[0] * 2.0)) droposstrs[0] = "" if self.show_dtg: if self.show_lathe_radius: droposstrs.insert( 1, droformat % ("Rad", positions[0], "R", axisdtg[0])) else: droposstrs.insert( 1, droformat % ("Dia", positions[0] * 2.0, "D", axisdtg[0] * 2.0)) else: if self.show_lathe_radius: droposstrs.insert(1, droformat % ("Rad", positions[0])) else: droposstrs.insert(1, diaformat % ("Dia", positions[0] * 2.0)) if self.show_velocity: posstrs.append(format % ("Vel", spd)) pos = 0 for i in range(9): if s.axis_mask & (1 << i): pos += 1 if self.is_lathe: pos += 1 droposstrs.insert(pos, " " + format % ("Vel", spd)) if self.show_dtg: posstrs.append(format % ("DTG", dtg)) return limit, homed, posstrs, droposstrs def realize(self, widget): gremlin.Gremlin.realize(self, widget) @rs274.glcanon.with_context def _load(self, filename): return self.load(filename)
class EMC_MDIHistory(Gtk.VBox, _EMC_ActionBase): ''' EMC_MDIHistory will store each MDI command to a file on your hard drive and display the grabbed commands in a treeview so they can be used again without typing the complete command again ''' __gtype_name__ = 'EMC_MDIHistory' __gproperties__ = { 'font_size_tree': (GObject.TYPE_INT, 'Font Size', 'The font size of the tree view text', 8, 96, 10, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'font_size_entry': (GObject.TYPE_INT, 'Font Size', 'The font size of the entry text', 8, 96, 10, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), 'use_double_click': (GObject.TYPE_BOOLEAN, 'Enable submit a command using a double click', 'A double click on an entry will submit the selected command directly\nIt is not recommended to use this on real machines', False, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'exit': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ()), } def __init__(self, *a, **kw): Gtk.VBox.__init__(self, *a, **kw) self.use_double_click = False self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) self.no_home_required = int( self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = Gtk.ListStore(str) self.tv = Gtk.TreeView() self.default_font = self.tv.get_style().font_desc.to_string() self.tv.modify_font(Pango.FontDescription(self.default_font)) self.tv.set_model(self.model) self.cell = Gtk.CellRendererText() self.col = Gtk.TreeViewColumn(_("Command")) self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) self.tv.get_selection().set_mode(Gtk.SelectionMode.NONE) scroll = Gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC scroll.props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC self.entry = Gtk.Entry() self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "gtk-ok") self.entry.modify_font(Pango.FontDescription(self.default_font)) self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True, True, 0) self.pack_start(self.entry, False, False, 0) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on())) self.gstat.connect( 'interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) # this time lambda with two parameters, as not all homed will send also the unhomed joints self.gstat.connect( 'not-all-homed', lambda w, uj: self.set_sensitive(self.no_home_required)) self.reload() self.show_all() def reload(self): self.model.clear() try: fp = open(self.filename) except: return lines = map(str.strip, fp.readlines()) fp.close() lines = filter(bool, lines) for l in lines: self.model.append((l, )) #path = (len(list(lines))-1,) path = 0 #TODO: breaks the functionality self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') def submit(self, *a): cmd = self.entry.get_text() if cmd == 'HALMETER' or cmd == 'halmeter': self.load_halmeter() return elif cmd == 'STATUS' or cmd == 'status': self.load_status() return elif cmd == 'HALSHOW' or cmd == 'halshow': self.load_halshow() return if not cmd: return ensure_mode(self.gstat.stat, self.linuxcnc, linuxcnc.MODE_MDI) self.linuxcnc.mdi(cmd) self.entry.set_text('') self.entry.grab_focus() add_to_file = True # we need to put this in a try, because if the hal mdi history file is # empty, the model is empty and we will get an None iter! try: actual = self.tv.get_cursor()[0] iter = self.model.get_iter(actual) old_cmd = self.model.get_value(iter, 0) lastiter = self._get_iter_last(self.model) len = int(self.model.get_string_from_iter(lastiter)) if actual[0] == len and old_cmd == cmd: add_to_file = False except: pass if add_to_file: try: fp = open(self.filename, 'a') fp.write(cmd + "\n") fp.close() except: pass last = self.model.append((cmd, )) path = self.model.get_path(last) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') self.entry.grab_focus() self.tv.get_selection().set_mode(Gtk.SelectionMode.NONE) def select(self, w): idx = w.get_cursor()[0] if idx is None: return True self.entry.set_text(self.model[idx][0]) self.entry.grab_focus() self.entry.set_position(-1) def on_key_press_event(self, w, event): # get the keyname keyname = Gdk.keyval_name(event.keyval) # print(keyname) idx = self.tv.get_cursor()[0] if idx is None: return True lastiter = self._get_iter_last(self.model) len = int(self.model.get_string_from_iter(lastiter)) #if nothing is selected, we need to activate the last one on up key selection = self.tv.get_selection() _, selected = selection.get_selected() if keyname == 'Up': self.tv.get_selection().set_mode(Gtk.SelectionMode.SINGLE) if not selected: self.tv.set_cursor(len) else: if idx[0] > 0: self.tv.set_cursor(idx[0] - 1) else: self.tv.set_cursor(idx[0]) return True if keyname == 'Down': if not selected: return True self.tv.get_selection().set_mode(Gtk.SelectionMode.SINGLE) if idx[0] < len: self.tv.set_cursor(idx[0] + 1) else: self.tv.set_cursor(idx[0]) self.entry.set_text('') self.entry.grab_focus() self.tv.get_selection().set_mode(Gtk.SelectionMode.NONE) return True if keyname == 'Escape': self.entry.set_text('') self.entry.grab_focus() self.tv.get_selection().set_mode(Gtk.SelectionMode.NONE) def on_button_press_event(self, w, event): idx = w.get_cursor()[0] if idx is None: return True self.tv.get_selection().set_mode(Gtk.SelectionMode.SINGLE) self.entry.set_text(self.model[idx][0]) self.entry.grab_focus() self.entry.set_position(-1) if event.type == Gdk.EventType._2BUTTON_PRESS: print("Double Click", self.use_double_click) if self.use_double_click: self.submit() def load_halmeter(self): p = os.popen("halmeter &") def load_status(self): p = os.popen("linuxcnctop > /dev/null &", "w") def load_halshow(self): try: p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH)) except: self.entry.set_text(_("ERROR loading halshow")) def _get_iter_last(self, model): itr = model.get_iter_first() last = None while itr: last = itr itr = model.iter_next(itr) return last def _change_font_entry(self, value): font = self.default_font.split()[0] new_font = font + " " + str(value) self.entry.modify_font(Pango.FontDescription(new_font)) def _change_font_tree(self, value): font = self.default_font.split()[0] new_font = font + " " + str(value) self.tv.modify_font(Pango.FontDescription(new_font)) # Get property def do_get_property(self, property): name = property.name.replace('-', '_') if name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) # Set property def do_set_property(self, property, value): try: name = property.name.replace('-', '_') if name in self.__gproperties.keys(): setattr(self, name, value) self.queue_draw() if name == "font_size_tree": self._change_font_tree(value) if name == "font_size_entry": self._change_font_entry(value) if name == "use_double_click": self.use_double_click = value else: raise AttributeError('unknown property %s' % property.name) except: pass
class EMC_MDIHistory(gtk.VBox, _EMC_ActionBase): ''' EMC_MDIHistory will store each MDI command to a file on your hard drive and display the grabbed commands in a treeview so they can be used again without typing the complete comand again ''' __gtype_name__ = 'EMC_MDIHistory' __gproperties__ = { 'font_size_tree' : (gobject.TYPE_INT, 'Font Size', 'The font size of the tree view text', 8, 96, 10, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'font_size_entry' : (gobject.TYPE_INT, 'Font Size', 'The font size of the entry text', 8, 96, 10, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_double_click' : (gobject.TYPE_BOOLEAN, 'Enable submit a command using a double click', 'A double click on an entry will submit the selected command directly\nIt is not recommended to use this on real machines', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'exit': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), } def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.use_double_click = False self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) self.no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.default_font = self.tv.get_style().font_desc.to_string() self.tv.modify_font(pango.FontDescription(self.default_font)) self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Command") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) self.tv.get_selection().set_mode(gtk.SELECTION_NONE) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.modify_font(pango.FontDescription(self.default_font)) self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on())) self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) # this time lambda with two parameters, as not all homed will send also the unhomed joints self.gstat.connect('not-all-homed', lambda w,uj: self.set_sensitive(self.no_home_required) ) self.reload() self.show_all() def reload(self): self.model.clear() try: fp = open(self.filename) except: return lines = map(str.strip, fp.readlines()) fp.close() lines = filter(bool, lines) for l in lines: self.model.append((l,)) path = (len(lines)-1,) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') def submit(self, *a): cmd = self.entry.get_text() if cmd == 'HALMETER' or cmd == 'halmeter': self.load_halmeter() return elif cmd == 'STATUS' or cmd == 'status': self.load_status() return elif cmd == 'HALSHOW' or cmd == 'halshow': self.load_halshow() return if not cmd: return ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI) self.linuxcnc.mdi(cmd) self.entry.set_text('') self.entry.grab_focus() add_to_file = True # we need to put this in a try, because if the hal mdi history file is # empty, the model is empty and we will get an None iter! try: actual = self.tv.get_cursor()[0] iter = self.model.get_iter(actual) old_cmd = self.model.get_value(iter,0) lastiter = self._get_iter_last(self.model) len = int(self.model.get_string_from_iter(lastiter)) if actual[0] == len and old_cmd == cmd: add_to_file = False except: pass if add_to_file: try: fp = open(self.filename, 'a') fp.write(cmd + "\n") fp.close() except: pass last = self.model.append((cmd,)) path = self.model.get_path(last) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') self.entry.grab_focus() self.tv.get_selection().set_mode(gtk.SELECTION_NONE) def select(self, w): idx = w.get_cursor()[0] if idx is None: return True self.entry.set_text(self.model[idx][0]) self.entry.grab_focus() self.entry.set_position(-1) def on_key_press_event(self,w,event): # get the keyname keyname = gtk.gdk.keyval_name(event.keyval) # print(keyname) idx = self.tv.get_cursor()[0] if idx is None: return True lastiter = self._get_iter_last(self.model) len = int(self.model.get_string_from_iter(lastiter)) #if nothing is selected, we need to activate the last one on up key selection = self.tv.get_selection() _, selected = selection.get_selected() if keyname == 'Up': self.tv.get_selection().set_mode(gtk.SELECTION_SINGLE) if not selected: self.tv.set_cursor(len) else: if idx[0] > 0: self.tv.set_cursor(idx[0] - 1) else: self.tv.set_cursor(idx[0]) return True if keyname == 'Down': if not selected: return True self.tv.get_selection().set_mode(gtk.SELECTION_SINGLE) if idx[0] < len: self.tv.set_cursor(idx[0] + 1) else: self.tv.set_cursor(idx[0]) self.entry.set_text('') self.entry.grab_focus() self.tv.get_selection().set_mode(gtk.SELECTION_NONE) return True if keyname == 'Escape': self.entry.set_text('') self.entry.grab_focus() self.tv.get_selection().set_mode(gtk.SELECTION_NONE) def on_button_press_event(self,w,event): idx = w.get_cursor()[0] if idx is None: return True self.tv.get_selection().set_mode(gtk.SELECTION_SINGLE) self.entry.set_text(self.model[idx][0]) self.entry.grab_focus() self.entry.set_position(-1) if event.type == gtk.gdk._2BUTTON_PRESS: print("Double Click", self.use_double_click) if self.use_double_click: self.submit() def load_halmeter(self): p = os.popen("halmeter &") def load_status(self): p = os.popen("linuxcnctop > /dev/null &","w") def load_halshow(self): try: p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH)) except: self.entry.set_text('ERROR loading halshow') def _get_iter_last(self, model): itr = model.get_iter_first() last = None while itr: last = itr itr = model.iter_next(itr) return last def _change_font_entry(self, value): font = self.default_font.split()[0] new_font = font +" " + str(value) self.entry.modify_font(pango.FontDescription(new_font)) def _change_font_tree(self, value): font = self.default_font.split()[0] new_font = font +" " + str(value) self.tv.modify_font(pango.FontDescription(new_font)) # Get property def do_get_property(self, property): name = property.name.replace('-', '_') if name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) # Set property def do_set_property(self, property, value): try: name = property.name.replace('-', '_') if name in self.__gproperties.keys(): setattr(self, name, value) self.queue_draw() if name == "font_size_tree": self._change_font_tree(value) if name == "font_size_entry": self._change_font_entry(value) if name == "use_double_click": self.use_double_click = value else: raise AttributeError('unknown property %s' % property.name) except: pass
class OffsetPage(gtk.VBox): __gtype_name__ = 'OffsetPage' __gproperties__ = { 'display_units_mm' : (gobject.TYPE_BOOLEAN, 'Display Units', 'Display in metric or not', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'mm_text_template' : (gobject.TYPE_STRING, 'Text template for Metric Units', 'Text template to display. Python formatting may be used for one variable', "%10.3f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'imperial_text_template' : (gobject.TYPE_STRING, 'Text template for Imperial Units', 'Text template to display. Python formatting may be used for one variable', "%9.4f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'font' : (gobject.TYPE_STRING, 'Pango Font', 'Display font to use', "sans 12", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'highlight_color' : (gtk.gdk.Color.__gtype__, 'Highlight color', "", gobject.PARAM_READWRITE), 'foreground_color' : (gtk.gdk.Color.__gtype__, 'Active text color', "", gobject.PARAM_READWRITE), 'hide_columns' : (gobject.TYPE_STRING, 'Hidden Columns', 'A no-spaces list of axes to hide: xyzabcuvw and t are the options', "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'hide_rows' : (gobject.TYPE_STRING, 'Hidden Rows', 'A no-spaces list of rows to hide: 0123456789abc are the options' , "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'selection_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING,)), } def __init__(self, filename = None, *a, **kw): super(OffsetPage, self).__init__() self.gstat = GStat() self.filename = filename self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.cmd = linuxcnc.command() self.hash_check = None self.display_units_mm = 0 # imperial self.machine_units_mm = 0 # imperial self.program_units = 0 # imperial self.display_follows_program = False # display units are chosen indepenadently of G20/G21 self.font = "sans 12" self.editing_mode = False self.highlight_color = gtk.gdk.Color("lightblue") self.foreground_color = gtk.gdk.Color("red") self.unselectable_color = gtk.gdk.Color("lightgray") self.hidejointslist = [] self.hidecollist = [] self.wTree = gtk.Builder() self.wTree.set_translation_domain("linuxcnc") # for locale translations self.wTree.add_from_file(os.path.join(datadir, "offsetpage.glade")) self.current_system = None self.selection_mask = () self.axisletters = ["x", "y", "z", "a", "b", "c", "u", "v", "w"] # global references self.store = self.wTree.get_object("liststore2") self.all_window = self.wTree.get_object("all_window") self.view2 = self.wTree.get_object("treeview2") self.view2.connect('button_press_event', self.on_treeview2_button_press_event) self.selection = self.view2.get_selection() self.selection.set_mode(gtk.SELECTION_SINGLE) self.selection.connect("changed", self.on_selection_changed) self.modelfilter = self.wTree.get_object("modelfilter") self.edit_button = self.wTree.get_object("edit_button") self.edit_button.connect('toggled', self.set_editing) zero_g92_button = self.wTree.get_object("zero_g92_button") zero_g92_button.connect('clicked', self.zero_g92) zero_rot_button = self.wTree.get_object("zero_rot_button") zero_rot_button.connect('clicked', self.zero_rot) self.set_font(self.font) self.modelfilter.set_visible_column(10) self.buttonbox = self.wTree.get_object("buttonbox") for col, name in enumerate(AXISLIST): if col > 9:break temp = self.wTree.get_object("cell_%s" % name) temp.connect('edited', self.col_editted, col) temp = self.wTree.get_object("cell_name") temp.connect('edited', self.col_editted, 10) # reparent offsetpage box from Glades top level window to widgets VBox window = self.wTree.get_object("offsetpage_box") window.reparent(self) # check the ini file if UNITS are set to mm # first check the global settings # if not available then the X axis units try: self.inifile = self.linuxcnc.ini(INIPATH) units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: units = self.inifile.find("AXIS_0", "UNITS") except: print "**** Offsetpage widget ERROR: LINEAR_UNITS not found in INI's TRAJ section" units = "inch" # now setup the conversion array depending on the machine native units if units == "mm" or units == "metric" or units == "1.0": self.machine_units_mm = 1 self.conversion = [1.0 / 25.4] * 3 + [1] * 3 + [1.0 / 25.4] * 3 else: self.machine_units_mm = 0 self.conversion = [25.4] * 3 + [1] * 3 + [25.4] * 3 # check linuxcnc status every half second gobject.timeout_add(500, self.periodic_check) # Reload the offsets into display def reload_offsets(self): g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 = self.read_file() if g54 == None: return # Get the offsets arrays and convert the units if the display # is not in machine native units g5x = self.status.g5x_offset tool = self.status.tool_offset g92 = self.status.g92_offset rot = self.status.rotation_xy if self.display_units_mm != self.machine_units_mm: g5x = self.convert_units(g5x) tool = self.convert_units(tool) g92 = self.convert_units(g92) g54 = self.convert_units(g54) g55 = self.convert_units(g55) g56 = self.convert_units(g56) g57 = self.convert_units(g57) g58 = self.convert_units(g58) g59 = self.convert_units(g59) g59_1 = self.convert_units(g59_1) g59_2 = self.convert_units(g59_2) g59_3 = self.convert_units(g59_3) # set the text style based on unit type if self.display_units_mm: tmpl = self.mm_text_template else: tmpl = self.imperial_text_template degree_tmpl = "%11.2f" # fill each row of the liststore fron the offsets arrays for row, i in enumerate([tool, g5x, rot, g92, g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3]): for column in range(0, 9): if row == 2: if column == 2: self.store[row][column + 1] = locale.format(degree_tmpl, rot) else: self.store[row][column + 1] = " " else: self.store[row][column + 1] = locale.format(tmpl, i[column]) # set the current system's label's color - to make it stand out a bit if self.store[row][0] == self.current_system: self.store[row][13] = self.foreground_color else: self.store[row][13] = None # mark unselectable rows a dirrerent color if self.store[row][0] in self.selection_mask: self.store[row][12] = self.unselectable_color # This is for adding a filename path after the offsetpage is already loaded. def set_filename(self, filename): self.filename = filename self.reload_offsets() # We read the var file directly # and pull out the info we need # if anything goes wrong we set all the info to 0 def read_file(self): try: g54 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g55 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g56 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g57 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g58 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59_3 = [0, 0, 0, 0, 0, 0, 0, 0, 0] if self.filename == None: return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 if not os.path.exists(self.filename): return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 logfile = open(self.filename, "r").readlines() for line in logfile: temp = line.split() param = int(temp[0]) data = float(temp[1]) if 5229 >= param >= 5221: g54[param - 5221] = data elif 5249 >= param >= 5241: g55[param - 5241] = data elif 5269 >= param >= 5261: g56[param - 5261] = data elif 5289 >= param >= 5281: g57[param - 5281] = data elif 5309 >= param >= 5301: g58[param - 5301] = data elif 5329 >= param >= 5321: g59[param - 5321] = data elif 5349 >= param >= 5341: g59_1[param - 5341] = data elif 5369 >= param >= 5361: g59_2[param - 5361] = data elif 5389 >= param >= 5381: g59_3[param - 5381] = data return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 except: return None, None, None, None, None, None, None, None, None # This allows hiding or showing columns from a text string of columnns # eg list ='ab' # default, all the columns are shown def set_col_visible(self, list, bool): try: for index in range(0, len(list)): colstr = str(list[index]) colnum = "xyzabcuvwt".index(colstr.lower()) name = AXISLIST[colnum + 1] renderer = self.wTree.get_object(name) renderer.set_property('visible', bool) except: pass # hide/show the offset rows from a text string of row ids # eg list ='123' def set_row_visible(self, list, bool): try: for index in range(0, len(list)): rowstr = str(list[index]) rownum = "0123456789abcd".index(rowstr.lower()) self.store[rownum][10] = bool except: pass # This does the units conversion # it just multiplies the two arrays def convert_units(self, v): c = self.conversion return map(lambda x, y: x * y, v, c) # make the cells editable and highlight them def set_editing(self, widget): state = widget.get_active() # stop updates from linuxcnc self.editing_mode = state # highlight editable rows if state: color = self.highlight_color else: color = None # Set rows editable for i in range(1, 13): if not self.store[i][0] in('G5x', 'Rot', 'G92', 'G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1', 'G59.2', 'G59.3'): continue if self.store[i][0] in self.selection_mask: continue self.store[i][11] = state self.store[i][12] = color self.queue_draw() # When the column is edited this does the work # TODO the edited column does not end up showing the editted number even though linuxcnc # registered the change def col_editted(self, widget, filtered_path, new_text, col): (store_path,) = self.modelfilter.convert_path_to_child_path(filtered_path) row = store_path axisnum = col - 1 # print "EDITED:", new_text, col, int(filtered_path), row, "axis num:", axisnum def system_to_p(system): convert = { "G54":1, "G55":2, "G56":3, "G57":4, "G58":5, "G59":6, "G59.1":7, "G59.2":8, "G59.3":9} try: pnum = convert[system] except: pnum = None return pnum # Hack to not edit any rotational offset but Z axis if row == 2 and not col == 3: return # set the text style based on unit type if self.display_units_mm: tmpl = lambda s: self.mm_text_template % s else: tmpl = lambda s: self.imperial_text_template % s # allow 'name' columnn text to be arbitrarily changed if col == 10: self.store[row][14] = new_text return # set the text in the table try: self.store[row][col] = locale.format("%10.4f", locale.atof(new_text)) except: print "offsetpage widget error: unrecognized float input" # make sure we switch to correct units for machine and rotational, row 2, does not get converted try: if not self.display_units_mm == self.program_units and not row == 2: if self.program_units == 1: convert = 25.4 else: convert = 1.0 / 25.4 qualified = float(locale.atof(new_text)) * convert else: qualified = float(locale.atof(new_text)) except: print 'error' # now update linuxcnc to the change try: global lncnc_runnning if lncnc_running: if self.status.task_mode != self.linuxcnc.MODE_MDI: self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() if row == 1: self.cmd.mdi("G10 L2 P0 %s %10.4f" % (self.axisletters[axisnum], qualified)) elif row == 2: if col == 3: self.cmd.mdi("G10 L2 P0 R %10.4f" % (qualified)) elif row == 3: self.cmd.mdi("G92 %s %10.4f" % (self.axisletters[axisnum], qualified)) else: pnum = system_to_p(self.store[row][0]) if not pnum == None: self.cmd.mdi("G10 L2 P%d %s %10.4f" % (pnum, self.axisletters[axisnum], qualified)) self.cmd.mode(self.linuxcnc.MODE_MANUAL) self.cmd.wait_complete() self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.gstat.emit('reload-display') except: print "offsetpage widget error: MDI call error" self.reload_offsets() # callback to cancel G92 when button pressed def zero_g92(self, widget): # print "zero g92" if lncnc_running: try: if self.status.task_mode != self.linuxcnc.MODE_MDI: self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.cmd.mdi("G92.1") self.cmd.mode(self.linuxcnc.MODE_MANUAL) self.cmd.wait_complete() self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.gstat.emit('reload-display') except: print "MDI error in offsetpage widget -zero G92" # callback to zero rotational offset when button pressed def zero_rot(self, widget): # print "zero rotation offset" if lncnc_running: try: if self.status.task_mode != self.linuxcnc.MODE_MDI: self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.cmd.mdi("G10 L2 P0 R 0") self.cmd.mode(self.linuxcnc.MODE_MANUAL) self.cmd.wait_complete() self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.gstat.emit('reload-display') except: print "MDI error in offsetpage widget-zero rotational offset" # check for linnuxcnc ON and IDLE which is the only safe time to edit the tool file. # if in editing mode don't update else you can't actually edit def periodic_check(self): convert = ("None", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2", "G59.3") try: self.status.poll() on = self.status.task_state > linuxcnc.STATE_OFF idle = self.status.interp_state == linuxcnc.INTERP_IDLE self.edit_button.set_sensitive(bool(on and idle)) self.current_system = convert[self.status.g5x_index] self.program_units = int(self.status.program_units == 2) if self.display_follows_program: self.display_units_mm = self.program_units global lncnc_running lncnc_running = True except: self.current_system = "G54" lncnc_running = False if self.filename and not self.editing_mode: self.reload_offsets() return True # sets the color when editing is active def set_highlight_color(self, value): self.highlight_color = gtk.gdk.Color(value) # sets the text color of the current system description name def set_foreground_color(self, value): self.foreground_color = gtk.gdk.Color(value) # Allows you to set the text font of all the rows and columns def set_font(self, value): for col, name in enumerate(AXISLIST): if col > 10:break temp = self.wTree.get_object("cell_" + name) temp.set_property('font', value) # helper function to set the units to inch def set_to_inch(self): self.display_units_mm = 0 # helper function to set the units to mm def set_to_mm(self): self.display_units_mm = 1 def set_display_follows_program_units(self): self.display_follows_program = True def set_display_independent_units(self): self.display_follows_program = False # helper function to hide control buttons def hide_buttonbox(self, state): if state: self.buttonbox.hide() else: self.buttonbox.show() # Mark the active system with cursor highlight def mark_active(self, system): try: pathlist = [] for row in self.modelfilter: if row[0] == system: pathlist.append(row.path) if len(pathlist) == 1: self.selection.select_path(pathlist[0]) except: print "offsetpage_widget error: cannot select coordinate system", system # Get the selected row the user clicked def get_selected(self): model, iter = self.selection.get_selected() if iter: system = model.get_value(iter, 0) name = model.get_value(iter, 14) # print "System:%s Name:%s"% (system,name) return system, name else: return None, None def on_selection_changed(self, treeselection): system, name = self.get_selected() # print self.status.g5x_index if system in self.selection_mask: self.mark_active(self.current_system) self.emit("selection_changed", system, name) def set_names(self, names): for offset, name in names: for row in range(0, 13): if offset == self.store[row][0]: self.store[row][14] = name def get_names(self): temp = [] for row in range(0, 13): temp.append([self.store[row][0], self.store[row][14]]) return temp # For single click selection when in edit mode def on_treeview2_button_press_event(self, widget, event): if event.button == 1 : # left click try: path, model, x, y = widget.get_path_at_pos(int(event.x), int(event.y)) self.view2.set_cursor(path, None, True) except: pass # standard Gobject method def do_get_property(self, property): name = property.name.replace('-', '_') if name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) # standard Gobject method # This is so that in the Glade editor, you can change the display def do_set_property(self, property, value): name = property.name.replace('-', '_') if name == 'font': try: self.set_font(value) except: pass if name == 'hide_columns': self.set_col_visible("xyzabcuvwt", True) self.set_col_visible("%s" % value, False) if name == 'hide_rows': self.set_row_visible("0123456789abc", True) self.set_row_visible("%s" % value, False) if name in self.__gproperties.keys(): setattr(self, name, value) # boiler code for variable access def __getitem__(self, item): return getattr(self, item) def __setitem__(self, item, value): return setattr(self, item, value)
""" import sys, os, subprocess import traceback import hal from optparse import Option, OptionParser import gtk import gtk.glade import gobject import signal import gladevcp.makepins from gladevcp.gladebuilder import GladeBuilder from gladevcp import xembed from hal_glib import GStat GSTAT = GStat() options = [ Option( '-c', dest='component', metavar='NAME' , help="Set component name to NAME. Default is basename of UI file") , Option( '-d', action='store_true', dest='debug' , help="Enable debug output") , Option( '-g', dest='geometry', default="", help="""Set geometry WIDTHxHEIGHT+XOFFSET+YOFFSET. Values are in pixel units, XOFFSET/YOFFSET is referenced from top left of screen use -g WIDTHxHEIGHT for just setting size or -g +XOFFSET+YOFFSET for just position""") , Option( '-H', dest='halfile', metavar='FILE' , help="execute hal statements from FILE with halcmd after the component is set up and ready") , Option( '-m', dest='maximum', default=False, help="Force panel window to maxumize") , Option( '-r', dest='gtk_rc', default="", help="read custom GTK rc file to set widget style") , Option( '-R', dest='gtk_workaround', action='store_false',default=True, help="disable workaround for GTK bug to properly read ~/.gtkrc-2.0 gtkrc files")
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gsignals__ = { 'line-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_INT,)), 'gcode_error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), } __gproperties__ = { 'view' : ( gobject.TYPE_STRING, 'View type', 'Default view: p, x, y, y2, z, z2', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro' : ( gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units' : ( gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative' : ( gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded' : ( gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option' : ( gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits' : ( gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot' : ( gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity' : ( gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program' : ( gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids' : ( gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool' : ( gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg' : ( gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_lathe_radius' : ( gobject.TYPE_BOOLEAN, 'Show Lathe Radius', 'Show X axis in Radius', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'grid_size' : ( gobject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode' : ( gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_default_controls' : ( gobject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'mouse_btn_mode' : ( gobject.TYPE_INT, 'Mouse Button Mode', ('Mousebutton assignment, l means left, m middle, r right \n' '0 = default: l-rotate, m-move, r-zoom \n' '1 = l-zoom, m-move, r-rotate\n' '2 = l-move, m-rotate, r-zoom\n' '3 = l-zoom, m-rotate, r-move\n' '4 = l-move, m-zoom, r-rotate\n' '5 = l-rotate, m-zoom, r-move\n' '6 = l-move, m-zoom, r-zoom'), 0, 6, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): gobject.GObject.__init__(self) inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self._reload_filename = None self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.gstat.connect('reload-display', self.reloadfile) self.show() def reloadfile(self,w): try: self.fileloaded(None,self._reload_filename) except: pass def fileloaded(self,w,f): self._reload_filename=f try: self._load(f) except AttributeError,detail: #AttributeError: 'NoneType' object has no attribute 'gl_end' print 'hal_gremlin: continuing after',detail
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gproperties__ = { 'view' : ( gobject.TYPE_STRING, 'View type', 'Default view: p, x, y, y2, z, z2', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro' : ( gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units' : ( gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative' : ( gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded' : ( gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option' : ( gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits' : ( gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot' : ( gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity' : ( gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program' : ( gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids' : ( gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool' : ( gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg' : ( gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_lathe_radius' : ( gobject.TYPE_BOOLEAN, 'Show Lathe Radius', 'Show X axis in Radius', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'grid_size' : ( gobject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode' : ( gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_default_controls' : ( gobject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self.gstat = GStat() self.gstat.connect('file-loaded', lambda w, f: self._load(f)) self.show() def do_get_property(self, property): name = property.name.replace('-', '_') if name == 'view': return self.current_view elif name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) def do_set_property(self, property, value): name = property.name.replace('-', '_') if name == 'view': view = value.lower() if self.lathe_option: if view not in ['p','y','y2']: return False elif view not in ['p', 'x', 'y', 'z', 'z2']: return False self.current_view = view if self.initialised: self.set_current_view() elif name == 'enable_dro': self.enable_dro = value elif name == 'metric_units': self.metric_units = value elif name in self.__gproperties.keys(): setattr(self, name, value) else: raise AttributeError('unknown property %s' % property.name) self.queue_draw() return True # This overrides glcannon.py method so we can change the DRO def dro_format(self,s,spd,dtg,limit,homed,positions,axisdtg,g5x_offset,g92_offset,tlo_offset): if not self.enable_dro: return limit, homed, [''], [''] if self.metric_units: format = "% 6s:% 9.3f" if self.show_dtg: droformat = " " + format + " DTG %1s:% 9.3f" else: droformat = " " + format offsetformat = "% 5s %1s:% 9.3f G92 %1s:% 9.3f" rotformat = "% 5s %1s:% 9.3f" else: format = "% 6s:% 9.4f" if self.show_dtg: droformat = " " + format + " DTG %1s:% 9.4f" else: droformat = " " + format offsetformat = "% 5s %1s:% 9.4f G92 %1s:% 9.4f" rotformat = "% 5s %1s:% 9.4f" diaformat = " " + format posstrs = [] droposstrs = [] for i in range(9): a = "XYZABCUVW"[i] if s.axis_mask & (1<<i): posstrs.append(format % (a, positions[i])) if self.show_dtg: droposstrs.append(droformat % (a, positions[i], a, axisdtg[i])) else: droposstrs.append(droformat % (a, positions[i])) droposstrs.append("") for i in range(9): index = s.g5x_index if index<7: label = "G5%d" % (index+3) else: label = "G59.%d" % (index-6) a = "XYZABCUVW"[i] if s.axis_mask & (1<<i): droposstrs.append(offsetformat % (label, a, g5x_offset[i], a, g92_offset[i])) droposstrs.append(rotformat % (label, 'R', s.rotation_xy)) droposstrs.append("") for i in range(9): a = "XYZABCUVW"[i] if s.axis_mask & (1<<i): droposstrs.append(rotformat % ("TLO", a, tlo_offset[i])) # if its a lathe only show radius or diameter as per property # we have to adjust the homing icon to line up: if self.is_lathe(): if homed[0]: homed.pop(0) homed.pop(0) homed.insert(0,1) homed.insert(0,0) posstrs[0] = "" if self.show_lathe_radius: posstrs.insert(1, format % ("Rad", positions[0])) else: posstrs.insert(1, format % ("Dia", positions[0]*2.0)) droposstrs[0] = "" if self.show_dtg: if self.show_lathe_radius: droposstrs.insert(1, droformat % ("Rad", positions[0], "R", axisdtg[0])) else: droposstrs.insert(1, droformat % ("Dia", positions[0]*2.0, "D", axisdtg[0]*2.0)) else: if self.show_lathe_radius: droposstrs.insert(1, droformat % ("Rad", positions[0])) else: droposstrs.insert(1, diaformat % ("Dia", positions[0]*2.0)) if self.show_velocity: posstrs.append(format % ("Vel", spd)) pos=0 for i in range(9): if s.axis_mask & (1<<i): pos +=1 if self.is_lathe: pos +=1 droposstrs.insert(pos, " " + format % ("Vel", spd)) if self.show_dtg: posstrs.append(format % ("DTG", dtg)) return limit, homed, posstrs, droposstrs def realize(self, widget): gremlin.Gremlin.realize(self, widget) @rs274.glcanon.with_context def _load(self, filename): return self.load(filename)
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gproperties__ = { 'view' : ( gobject.TYPE_STRING, 'View type', 'Default view: x, y, z, p', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro' : ( gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units' : ( gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative' : ( gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded' : ( gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option' : ( gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits' : ( gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot' : ( gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity' : ( gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program' : ( gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids' : ( gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool' : ( gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg' : ( gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'grid_size' : ( gobject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode' : ( gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_default_controls' : ( gobject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self.gstat = GStat() self.gstat.connect('file-loaded', lambda w, f: self._load(f)) self.show() def do_get_property(self, property): name = property.name.replace('-', '_') if name == 'view': return self.current_view elif name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) def do_set_property(self, property, value): name = property.name.replace('-', '_') if name == 'view': view = value.lower() if self.lathe_option and view not in ['p','y']: return False if view not in ['x', 'y', 'z', 'p']: return False self.current_view = view if self.initialised: self.set_current_view() elif name == 'enable_dro': self.enable_dro = value elif name == 'metric_units': self.metric_units = value elif name in self.__gproperties.keys(): setattr(self, name, value) else: raise AttributeError('unknown property %s' % property.name) self.queue_draw() return True def posstrs(self): l, h, p, d = gremlin.Gremlin.posstrs(self) if self.enable_dro: return l, h, p, d return l, h, [''], [''] def realize(self, widget): gremlin.Gremlin.realize(self, widget) @rs274.glcanon.with_context def _load(self, filename): return self.load(filename)
class MacroSelect(gtk.VBox, _EMC_ActionBase): __gtype_name__ = 'MacroSelect' __gsignals__ = { 'macro-submitted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ( gobject.TYPE_STRING, gobject.TYPE_STRING, )), } def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. try: inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) no_home_required = int( self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) macros = self.inifile.findall("MACROS", "MACRO") sub_path = self.inifile.find( "RS274NGC", "SUBROUTINE_PATH") or '~/linuxcnc/nc_files/macros' except: no_home_required = 1 macros = None sub_path = '~/linuxcnc/nc_files/macros' #path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.foldername = os.path.expanduser(sub_path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Macro Commands") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.tv.connect('key_press_event', self.on_key_press_event) self.tv.connect('button_press_event', self.on_button_press_event) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect( 'interp-idle', lambda w: self.set_sensitive(self.machine_on() and ( self.is_all_homed() or no_home_required))) self.gstat.connect( 'interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) self.reload() self.show_all() def reload(self): self.model.clear() files = [] try: for f in os.listdir(self.foldername): if f.endswith('.ngc'): with open(os.path.join(self.foldername, f), 'r') as temp: first_line = temp.readline().strip() print first_line if 'MACROCOMMAND' in first_line: files.append(first_line.strip('; MACROCOMMAND=')) except: pass lines = filter(bool, files) for l in lines: self.model.append((l, )) path = (len(lines) - 1, ) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') def submit(self, *a): cmd = self.entry.get_text() if cmd == 'HALMETER': self.load_halmeter() return elif cmd == 'STATUS': self.load_status() return elif cmd == 'HALSHOW': self.load_halshow() return if not cmd: return #ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI) name = cmd.split() path = self.foldername + "/" + name[0] + ".ngc" self.emit('macro-submitted', path, cmd) #self.linuxcnc.mdi(cmd) self.entry.set_text('') self.entry.grab_focus() def select(self, w): self.entry.set_text('') def on_key_press_event(self, w, event): idx = w.get_cursor()[0] if idx is None: return True if gtk.gdk.keyval_name(event.keyval) == 'Return': self.entry.set_text(self.model[idx][0]) self.entry.grab_focus() return True def on_button_press_event(self, w, event): idx = w.get_cursor()[0] if idx is None: return True self.entry.set_text(self.model[idx][0]) def load_halmeter(self): p = os.popen("halmeter &") def load_status(self): p = os.popen("linuxcnctop > /dev/null &", "w") def load_halshow(self): try: p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH)) except: self.entry.set_text('ERROR loading halshow')
def get(self): if not self.linuxcnc: self.linuxcnc = linuxcnc.command() if not self.gstat: self.gstat = GStat() return self.linuxcnc, self.gstat.stat, self.gstat
def __init__(self): stat = self.linuxcnc_static.get()[1] GStat.__init__(self, stat)
class EMC_MDIHistory(gtk.VBox, _EMC_ActionBase): __gtype_name__ = 'EMC_MDIHistory' def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Command") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect( 'interp-idle', lambda w: self.set_sensitive(self.machine_on() and ( self.is_all_homed() or no_home_required))) self.gstat.connect( 'interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) self.reload() self.show_all() def reload(self): self.model.clear() try: fp = open(self.filename) except: return lines = map(str.strip, fp.readlines()) fp.close() lines = filter(bool, lines) for l in lines: self.model.append((l, )) path = (len(lines) - 1, ) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') def submit(self, *a): cmd = self.entry.get_text() if not cmd: return ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI) try: fp = open(self.filename, 'a') fp.write(cmd + "\n") fp.close() except: pass self.linuxcnc.mdi(cmd) last = self.model.append((cmd, )) path = self.model.get_path(last) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') self.entry.grab_focus() def select(self, w): idx = w.get_cursor()[0] if idx is None: return self.entry.set_text(self.model[idx][0])
def __init__(self, filename = None, *a, **kw): super(OffsetPage, self).__init__() self.gstat = GStat() self.filename = filename self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.cmd = linuxcnc.command() self.hash_check = None self.display_units_mm = 0 # imperial self.machine_units_mm = 0 # imperial self.program_units = 0 # imperial self.display_follows_program = False # display units are chosen indepenadently of G20/G21 self.font = "sans 12" self.editing_mode = False self.highlight_color = gtk.gdk.Color("lightblue") self.foreground_color = gtk.gdk.Color("red") self.unselectable_color = gtk.gdk.Color("lightgray") self.hidejointslist = [] self.hidecollist = [] self.wTree = gtk.Builder() self.wTree.set_translation_domain("linuxcnc") # for locale translations self.wTree.add_from_file(os.path.join(datadir, "offsetpage.glade")) self.current_system = None self.selection_mask = () self.axisletters = ["x", "y", "z", "a", "b", "c", "u", "v", "w"] # global references self.store = self.wTree.get_object("liststore2") self.all_window = self.wTree.get_object("all_window") self.view2 = self.wTree.get_object("treeview2") self.view2.connect('button_press_event', self.on_treeview2_button_press_event) self.selection = self.view2.get_selection() self.selection.set_mode(gtk.SELECTION_SINGLE) self.selection.connect("changed", self.on_selection_changed) self.modelfilter = self.wTree.get_object("modelfilter") self.edit_button = self.wTree.get_object("edit_button") self.edit_button.connect('toggled', self.set_editing) zero_g92_button = self.wTree.get_object("zero_g92_button") zero_g92_button.connect('clicked', self.zero_g92) zero_rot_button = self.wTree.get_object("zero_rot_button") zero_rot_button.connect('clicked', self.zero_rot) self.set_font(self.font) self.modelfilter.set_visible_column(10) self.buttonbox = self.wTree.get_object("buttonbox") for col, name in enumerate(AXISLIST): if col > 9:break temp = self.wTree.get_object("cell_%s" % name) temp.connect('edited', self.col_editted, col) temp = self.wTree.get_object("cell_name") temp.connect('edited', self.col_editted, 10) # reparent offsetpage box from Glades top level window to widgets VBox window = self.wTree.get_object("offsetpage_box") window.reparent(self) # check the ini file if UNITS are set to mm # first check the global settings # if not available then the X axis units try: self.inifile = self.linuxcnc.ini(INIPATH) units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: units = self.inifile.find("AXIS_0", "UNITS") except: print "**** Offsetpage widget ERROR: LINEAR_UNITS not found in INI's TRAJ section" units = "inch" # now setup the conversion array depending on the machine native units if units == "mm" or units == "metric" or units == "1.0": self.machine_units_mm = 1 self.conversion = [1.0 / 25.4] * 3 + [1] * 3 + [1.0 / 25.4] * 3 else: self.machine_units_mm = 0 self.conversion = [25.4] * 3 + [1] * 3 + [25.4] * 3 # check linuxcnc status every half second gobject.timeout_add(500, self.periodic_check)
# the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. import gobject import gtk import hal from hal_widgets import _HalWidgetBase from hal_glib import GStat GSTAT = GStat() class State_Label(gtk.Label, _HalWidgetBase): __gtype_name__ = "State_Label" __gproperties__ = { 'label_type': (gobject.TYPE_INT, 'Label type', '0:metric mode 1:Diameter mode 2:CSS Mode', 0, 2, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'true_text': (gobject.TYPE_STRING, 'True Text', 'Text to display when state is True', "True", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'false_text': (gobject.TYPE_STRING, 'False Text', 'Text to display when state is False', "False", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), }
def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = GStat.__new__(cls, *args, **kwargs) return cls._instance
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gproperties__ = { 'view': (gobject.TYPE_STRING, 'View type', 'Default view: p, x, y, y2, z, z2', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro': (gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units': (gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative': (gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded': (gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option': (gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits': (gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot': (gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity': (gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program': (gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids': (gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool': (gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg': (gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_lathe_radius': (gobject.TYPE_BOOLEAN, 'Show Lathe Radius', 'Show X axis in Radius', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'grid_size': (gobject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode': (gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_default_controls': (gobject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self._reload_filename = None self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.gstat.connect('reload-display', self.reloadfile) self.show() def reloadfile(self, w): try: self.fileloaded(None, self._reload_filename) except: pass def fileloaded(self, w, f): self._reload_filename = f try: self._load(f) except AttributeError, detail: #AttributeError: 'NoneType' object has no attribute 'gl_end' print 'hal_gremlin: continuing after', detail
class EMC_MDIHistory(gtk.VBox, _EMC_ActionBase): __gtype_name__ = 'EMC_MDIHistory' def __init__(self, *a, **kw): gtk.VBox.__init__(self, *a, **kw) self.gstat = GStat() # if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing. inifile = os.environ.get('INI_FILE_NAME', '/dev/null') self.ini = linuxcnc.ini(inifile) no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0) path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history' self.filename = os.path.expanduser(path) self.model = gtk.ListStore(str) self.tv = gtk.TreeView() self.tv.set_model(self.model) self.cell = gtk.CellRendererText() self.col = gtk.TreeViewColumn("Command") self.col.pack_start(self.cell, True) self.col.add_attribute(self.cell, 'text', 0) self.tv.append_column(self.col) self.tv.set_search_column(0) self.tv.set_reorderable(False) self.tv.set_headers_visible(True) scroll = gtk.ScrolledWindow() scroll.add(self.tv) scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC self.entry = gtk.Entry() self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok') self.entry.connect('activate', self.submit) self.entry.connect('icon-press', self.submit) self.tv.connect('cursor-changed', self.select) self.pack_start(scroll, True) self.pack_start(self.entry, False) self.gstat.connect('state-off', lambda w: self.set_sensitive(False)) self.gstat.connect('state-estop', lambda w: self.set_sensitive(False)) self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on() and ( self.is_all_homed() or no_home_required ) )) self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode())) self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on())) self.reload() self.show_all() def reload(self): self.model.clear() try: fp = open(self.filename) except: return lines = map(str.strip, fp.readlines()) fp.close() lines = filter(bool, lines) for l in lines: self.model.append((l,)) path = (len(lines)-1,) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') def submit(self, *a): cmd = self.entry.get_text() if not cmd: return ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI) try: fp = open(self.filename, 'a') fp.write(cmd + "\n") fp.close() except: pass self.linuxcnc.mdi(cmd) last = self.model.append((cmd,)) path = self.model.get_path(last) self.tv.scroll_to_cell(path) self.tv.set_cursor(path) self.entry.set_text('') self.entry.grab_focus() def select(self, w): idx = w.get_cursor()[0] if idx is None: return self.entry.set_text(self.model[idx][0])
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gproperties__ = { 'view': (gobject.TYPE_STRING, 'View type', 'Default view: x, y, z, p', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro': (gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units': (gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative': (gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded': (gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option': (gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits': (gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot': (gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity': (gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program': (gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids': (gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool': (gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg': (gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode': (gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): inifile = os.environ.get('INI_FILE_NAME', '/dev/null') inifile = linuxcnc.ini(inifile) gremlin.Gremlin.__init__(self, inifile) self.gstat = GStat() self.gstat.connect('file-loaded', lambda w, f: self._load(f)) self.show() def do_get_property(self, property): name = property.name.replace('-', '_') if name == 'view': return self.current_view elif name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) def do_set_property(self, property, value): name = property.name.replace('-', '_') if name == 'view': view = value.lower() if self.lathe_option and view not in ['p', 'y']: return False if view not in ['x', 'y', 'z', 'p']: return False self.current_view = view if self.initialised: self.set_current_view() elif name == 'enable_dro': self.enable_dro = value elif name == 'metric_units': self.metric_units = value elif name in self.__gproperties.keys(): setattr(self, name, value) else: raise AttributeError('unknown property %s' % property.name) self.queue_draw() return True def posstrs(self): l, h, p, d = gremlin.Gremlin.posstrs(self) if self.enable_dro: return l, h, p, d return l, h, [''], [''] def realize(self, widget): gremlin.Gremlin.realize(self, widget) @rs274.glcanon.with_context def _load(self, filename): return self.load(filename) # TODO fix this so it doesn't print twice and it should probably pop up a dialog def report_gcode_error(self, result, seq, filename): error_str = gcode.strerror(result) print("G-Code error in " + os.path.basename(filename) + "\n" + "Near line " + str(seq) + " of\n" + filename + "\n" + error_str + "\n")
class HAL_Gremlin(gremlin.Gremlin, _EMC_ActionBase): __gtype_name__ = "HAL_Gremlin" __gsignals__ = { 'line-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_INT, )), 'gcode_error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )), } __gproperties__ = { 'view': (gobject.TYPE_STRING, 'View type', 'Default view: p, x, y, y2, z, z2', 'p', gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'enable_dro': (gobject.TYPE_BOOLEAN, 'Enable DRO', 'Show DRO on graphics', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units': (gobject.TYPE_BOOLEAN, 'Use Metric Units', 'Show DRO in metric or imperial units', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_relative': (gobject.TYPE_BOOLEAN, 'Show Relative', 'Show DRO relative to active system or machine origin', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_commanded': (gobject.TYPE_BOOLEAN, 'Show Commanded', 'Show commanded or actual position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_extents_option': (gobject.TYPE_BOOLEAN, 'Show Extents', 'Show machine extents', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_limits': (gobject.TYPE_BOOLEAN, 'Show limits', 'Show machine limits', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_live_plot': (gobject.TYPE_BOOLEAN, 'Show live plot', 'Show machine plot', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_velocity': (gobject.TYPE_BOOLEAN, 'Show tool speed', 'Show tool velocity', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_program': (gobject.TYPE_BOOLEAN, 'Show program', 'Show program', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_rapids': (gobject.TYPE_BOOLEAN, 'Show rapids', 'Show rapid moves', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_tool': (gobject.TYPE_BOOLEAN, 'Show tool', 'Show tool', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_dtg': (gobject.TYPE_BOOLEAN, 'Show DTG', 'Show Distance To Go', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'show_lathe_radius': (gobject.TYPE_BOOLEAN, 'Show Lathe Radius', 'Show X axis in Radius', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'grid_size': (gobject.TYPE_FLOAT, 'Grid Size', 'Grid Size', 0, 100, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_joints_mode': (gobject.TYPE_BOOLEAN, 'Use joints mode', 'Use joints mode', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'use_default_controls': (gobject.TYPE_BOOLEAN, 'Use Default Mouse Controls', 'Use Default Mouse Controls', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'mouse_btn_mode': (gobject.TYPE_INT, 'Mouse Button Mode', ('Mousebutton assignment, l means left, m middle, r right \n' '0 = default: l-rotate, m-move, r-zoom \n' '1 = l-zoom, m-move, r-rotate\n' '2 = l-move, m-rotate, r-zoom\n' '3 = l-zoom, m-rotate, r-move\n' '4 = l-move, m-zoom, r-rotate\n' '5 = l-rotate, m-zoom, r-move\n' '6 = l-move, m-zoom, r-zoom'), 0, 6, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ def __init__(self, *a, **kw): gobject.GObject.__init__(self) ini_filename = os.environ.get('INI_FILE_NAME') if ini_filename is None: ini_filename = get_linuxcnc_ini_file() if ini_filename is not None: os.putenv('INI_FILE_NAME', ini_filename) os.environ['INI_FILE_NAME'] = ini_filename os.chdir(os.path.dirname(ini_filename)) inifile = linuxcnc.ini(ini_filename) gremlin.Gremlin.__init__(self, inifile) self._reload_filename = None self.gstat = GStat() self.gstat.connect('file-loaded', self.fileloaded) self.gstat.connect('reload-display', self.reloadfile) self.init_glcanondraw( trajcoordinates=self.inifile.find('TRAJ', 'COORDINATES'), kinsmodule=self.inifile.find('KINS', 'KINEMATICS')) self.show() def reloadfile(self, w): try: self.fileloaded(None, self._reload_filename) except: pass def fileloaded(self, w, f): self._reload_filename = f try: self._load(f) except AttributeError, detail: #AttributeError: 'NoneType' object has no attribute 'gl_end' print 'hal_gremlin: continuing after', detail
class Combi_DRO(gtk.VBox): ''' Combi_DRO will display an linuxcnc DRO with all three types at ones Combi_DRO = Combi_DRO(joint_number) joint_number is an integer in the range from 0 to 8 where 0 = X, 1 = Y, 2 = Z, etc. ''' __gtype_name__ = 'Combi_DRO' __gproperties__ = { 'joint_number' : (gobject.TYPE_INT, 'Joint Number', '0:X 1:Y 2:Z etc', 0, 8, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'actual' : (gobject.TYPE_BOOLEAN, 'Actual Position', 'Display Actual or Commanded Position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units' : (gobject.TYPE_BOOLEAN, 'Display in metric units', 'Display in metric or not', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'auto_units' : (gobject.TYPE_BOOLEAN, 'Change units according gcode', 'Units will toggle between metric and imperial according to gcode.', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'diameter' : (gobject.TYPE_BOOLEAN, 'Diameter Adjustment', 'Display Position As Diameter', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'mm_text_template' : (gobject.TYPE_STRING, 'Text template for Metric Units', 'Text template to display. Python formatting may be used for one variable', "%10.3f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'imperial_text_template' : (gobject.TYPE_STRING, 'Text template for Imperial Units', 'Text template to display. Python formatting may be used for one variable', "%9.4f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'homed_color' : (gtk.gdk.Color.__gtype__, 'homed color', 'Sets the color of the display when the axis is homed', gobject.PARAM_READWRITE), 'unhomed_color' : (gtk.gdk.Color.__gtype__, 'unhomed color', 'Sets the color of the display when the axis is not homed', gobject.PARAM_READWRITE), 'abs_color' : (gtk.gdk.Color.__gtype__, 'Absolute color', 'Sets the color of the display when absolute coordinates are used', gobject.PARAM_READWRITE), 'rel_color' : (gtk.gdk.Color.__gtype__, 'Relative color', 'Sets the color of the display when relative coordinates are used', gobject.PARAM_READWRITE), 'dtg_color' : (gtk.gdk.Color.__gtype__, 'DTG color', 'Sets the color of the display when dtg coordinates are used', gobject.PARAM_READWRITE), 'font_size' : (gobject.TYPE_INT, 'Font Size', 'The font size of the big numbers, the small ones will be 2.5 times smaler', 8, 96, 25, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'toggle_readout' : (gobject.TYPE_BOOLEAN, 'Enable toggling readout with click', 'The DRO will toggle between Absolut , Relativ and DTG with each mouse click.', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'cycle_time' : (gobject.TYPE_INT, 'Cycle Time', 'Time, in milliseconds, that display will sleep between polls', 100, 1000, 150, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)), 'units_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN,)), 'system_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 'exit': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), } # Init the class def __init__(self, joint_number = 0): super(Combi_DRO, self).__init__() # get the necessary connections to linuxcnc self.joint_number = self.joint = joint_number self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.gstat = GStat() self.get_ini_info = getiniinfo.GetIniInfo() # set some default values' self._ORDER = ["Rel", "Abs", "DTG"] self.system = "Rel" self.homed = False self.homed_color = gtk.gdk.Color("green") self.unhomed_color = gtk.gdk.Color("red") self.abs_color = gtk.gdk.Color("blue") self.rel_color = gtk.gdk.Color("black") self.dtg_color = gtk.gdk.Color("yellow") self.mm_text_template = "%10.3f" self.imperial_text_template = "%9.4f" self.font_size = 25 self.metric_units = True self.machine_units = _MM self.unit_convert = 1 self._auto_units = True self.toggle_readout = True self.cycle_time = 150 # Make the GUI and connect signals self.eventbox = gtk.EventBox() self.eventbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) self.add(self.eventbox) vbox_main = gtk.VBox(False, 0) self.eventbox.add(vbox_main) hbox_up = gtk.HBox(False, 0) vbox_main.pack_start(hbox_up) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size * 1000, 0, -1), (600, 0, -1)) self.lbl_axisletter = gtk.Label(_AXISLETTERS[self.joint_number]) self.lbl_axisletter.set_attributes(attr) hbox_up.pack_start(self.lbl_axisletter, False, False) vbox_ref_type = gtk.VBox(False, 0) hbox_up.pack_start(vbox_ref_type, False, False) lbl_space = gtk.Label("") vbox_ref_type.pack_start(lbl_space) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_main = gtk.Label(self.system) vbox_ref_type.pack_start(self.lbl_sys_main, False, False) self.lbl_sys_main.set_attributes(attr) self.main_dro = gtk.Label("9999.999") hbox_up.pack_start(self.main_dro) self.main_dro.set_alignment(1.0, 0.5) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size, 0, -1), (600, 0, -1)) self.main_dro.set_attributes(attr) hbox_down = gtk.HBox(False, 5) vbox_main.pack_start(hbox_down) self.lbl_sys_left = gtk.Label("Abs") hbox_down.pack_start(self.lbl_sys_left) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_left.set_attributes(attr) self.dro_left = gtk.Label("-11.111") hbox_down.pack_start(self.dro_left) self.dro_left.set_alignment(1.0, 0.5) self.dro_left.set_attributes(attr) self.lbl_sys_right = gtk.Label("DTG") hbox_down.pack_start(self.lbl_sys_right) self.lbl_sys_right.set_attributes(attr) self.dro_right = gtk.Label("22.222") hbox_down.pack_start(self.dro_right) self.dro_right.set_alignment(1.0, 0.5) self.dro_right.set_attributes(attr) self.eventbox.connect("button_press_event", self._on_eventbox_clicked) self.show_all() self.gstat.connect('not-all-homed', self._not_all_homed ) self.gstat.connect('all-homed', self._all_homed ) self.gstat.connect('homed', self._homed ) # This try is only needed because while working with glade # linuxcnc may not be working try: self.inifile = self.linuxcnc.ini(INIPATH) # check the ini file if UNITS are set to mm" # first check the global settings units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: # else then the X axis units units = self.inifile.find("AXIS_0", "UNITS") except: units = "inch" if units == "mm" or units == "metric" or units == "1.0": self.machine_units = _MM else: self.machine_units = _INCH # add the timer at a period of 100 ms gobject.timeout_add(self.cycle_time, self._periodic) # make an pango attribute to be used with several labels def _set_attributes(self, bgcolor, fgcolor, size, weight): attr = pango.AttrList() bg_color = pango.AttrBackground(bgcolor[0], bgcolor[1], bgcolor[2], 0, -1) attr.insert(bg_color) size_attr = pango.AttrSize(size[0], size[1], size[2]) attr.insert(size_attr) weight_attr = pango.AttrWeight(weight[0], weight[1], weight[2]) attr.insert(weight_attr) fg_color = pango.AttrForeground(fgcolor[0], fgcolor[1], fgcolor[2], 0, 13) attr.insert(fg_color) return attr # if the eventbox has been clicked, we like to toggle the DRO's def _on_eventbox_clicked(self, widget, event): if not self.toggle_readout: return self.toogle_readout() # Get propertys def do_get_property(self, property): name = property.name.replace('-', '_') if name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) # Set propertys def do_set_property(self, property, value): try: name = property.name.replace('-', '_') if name in self.__gproperties.keys(): setattr(self, name, value) self.queue_draw() if name in ('mm_text_template', 'imperial_text_template'): try: v = value % 0.0 except Exception, e: print "Invalid format string '%s': %s" % (value, e) return False if name == "homed_color": self.homed_color = value self._set_labels() if name == "unhomed_color": self.unhomed_color = value self._set_labels() if name == "abs_color": self.abs_color = value self._set_labels() if name == "rel_color": self.rel_color = value self._set_labels() if name == "dtg_color": self.dtg_color = value self._set_labels() if name == "auto_units": self._auto_units = value self._set_labels() if name == "joint_number": self.joint_number = self.joint = value self.change_axisletter(_AXISLETTERS[self.joint_number]) # check if LinuxCNC release does support JOINTS, if so # we have to check for corerct JOINT to watch homing state temp = self.get_ini_info.get_joints_amount() if temp: # in case of double letters, the joint / axis relation is # not 1 : 1, take care to react to the correct joint # for homing state (i.e. gantry XYYZ style) self.joint = self.joint_number temp = self.get_ini_info.get_coordinates().lower() temp = temp.replace(' ','') try: self.joint = temp.index(self.lbl_axisletter.get_text().lower()) except: self.joint = value if name == "font_size": self.font_size = value self._set_labels() if name == "toggle_readout": self.toggle_readout = value if name == "cycle_time": self.cycle_time = value if name in ('metric_units', 'actual', 'diameter'): setattr(self, name, value) self.queue_draw() else:
class OffsetPage(gtk.VBox): __gtype_name__ = 'OffsetPage' __gproperties__ = { 'display_units_mm': (gobject.TYPE_BOOLEAN, 'Display Units', 'Display in metric or not', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'mm_text_template': (gobject.TYPE_STRING, 'Text template for Metric Units', 'Text template to display. Python formatting may be used for one variable', "%10.3f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'imperial_text_template': (gobject.TYPE_STRING, 'Text template for Imperial Units', 'Text template to display. Python formatting may be used for one variable', "%9.4f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'font': (gobject.TYPE_STRING, 'Pango Font', 'Display font to use', "sans 12", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'highlight_color': (gtk.gdk.Color.__gtype__, 'Highlight color', "", gobject.PARAM_READWRITE), 'foreground_color': (gtk.gdk.Color.__gtype__, 'Active text color', "", gobject.PARAM_READWRITE), 'hide_columns': (gobject.TYPE_STRING, 'Hidden Columns', 'A no-spaces list of axes to hide: xyzabcuvw and t are the options', "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'hide_rows': (gobject.TYPE_STRING, 'Hidden Rows', 'A no-spaces list of rows to hide: 0123456789abc are the options', "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'selection_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ( gobject.TYPE_STRING, gobject.TYPE_STRING, )), } def __init__(self, filename=None, *a, **kw): super(OffsetPage, self).__init__() self.gstat = GStat() self.filename = filename self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.cmd = linuxcnc.command() self.hash_check = None self.display_units_mm = 0 # imperial self.machine_units_mm = 0 # imperial self.program_units = 0 # imperial self.display_follows_program = False # display units are chosen indepenadently of G20/G21 self.font = "sans 12" self.editing_mode = False self.highlight_color = gtk.gdk.Color("lightblue") self.foreground_color = gtk.gdk.Color("red") self.unselectable_color = gtk.gdk.Color("lightgray") self.hidejointslist = [] self.hidecollist = [] self.wTree = gtk.Builder() self.wTree.set_translation_domain( "linuxcnc") # for locale translations self.wTree.add_from_file(os.path.join(datadir, "offsetpage.glade")) self.current_system = None self.selection_mask = () self.axisletters = ["x", "y", "z", "a", "b", "c", "u", "v", "w"] # global references self.store = self.wTree.get_object("liststore2") self.all_window = self.wTree.get_object("all_window") self.view2 = self.wTree.get_object("treeview2") self.view2.connect('button_press_event', self.on_treeview2_button_press_event) self.selection = self.view2.get_selection() self.selection.set_mode(gtk.SELECTION_SINGLE) self.selection.connect("changed", self.on_selection_changed) self.modelfilter = self.wTree.get_object("modelfilter") self.edit_button = self.wTree.get_object("edit_button") self.edit_button.connect('toggled', self.set_editing) zero_g92_button = self.wTree.get_object("zero_g92_button") zero_g92_button.connect('clicked', self.zero_g92) zero_rot_button = self.wTree.get_object("zero_rot_button") zero_rot_button.connect('clicked', self.zero_rot) self.set_font(self.font) self.modelfilter.set_visible_column(10) self.buttonbox = self.wTree.get_object("buttonbox") for col, name in enumerate(AXISLIST): if col > 9: break temp = self.wTree.get_object("cell_%s" % name) temp.connect('edited', self.col_editted, col) temp = self.wTree.get_object("cell_name") temp.connect('edited', self.col_editted, 10) # reparent offsetpage box from Glades top level window to widgets VBox window = self.wTree.get_object("offsetpage_box") window.reparent(self) # check the ini file if UNITS are set to mm # first check the global settings # if not available then the X axis units try: self.inifile = self.linuxcnc.ini(INIPATH) units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: units = self.inifile.find("AXIS_X", "UNITS") except: print "**** Offsetpage widget ERROR: LINEAR_UNITS not found in INI's TRAJ section" units = "inch" # now setup the conversion array depending on the machine native units if units == "mm" or units == "metric" or units == "1.0": self.machine_units_mm = 1 self.conversion = [1.0 / 25.4] * 3 + [1] * 3 + [1.0 / 25.4] * 3 else: self.machine_units_mm = 0 self.conversion = [25.4] * 3 + [1] * 3 + [25.4] * 3 # check linuxcnc status every half second gobject.timeout_add(500, self.periodic_check) # Reload the offsets into display def reload_offsets(self): g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 = self.read_file() if g54 == None: return # Get the offsets arrays and convert the units if the display # is not in machine native units g5x = self.status.g5x_offset tool = self.status.tool_offset g92 = self.status.g92_offset rot = self.status.rotation_xy if self.display_units_mm != self.machine_units_mm: g5x = self.convert_units(g5x) tool = self.convert_units(tool) g92 = self.convert_units(g92) g54 = self.convert_units(g54) g55 = self.convert_units(g55) g56 = self.convert_units(g56) g57 = self.convert_units(g57) g58 = self.convert_units(g58) g59 = self.convert_units(g59) g59_1 = self.convert_units(g59_1) g59_2 = self.convert_units(g59_2) g59_3 = self.convert_units(g59_3) # set the text style based on unit type if self.display_units_mm: tmpl = self.mm_text_template else: tmpl = self.imperial_text_template degree_tmpl = "%11.2f" # fill each row of the liststore fron the offsets arrays for row, i in enumerate([ tool, g5x, rot, g92, g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 ]): for column in range(0, 9): if row == 2: if column == 2: self.store[row][column + 1] = locale.format( degree_tmpl, rot) else: self.store[row][column + 1] = " " else: self.store[row][column + 1] = locale.format( tmpl, i[column]) # set the current system's label's color - to make it stand out a bit if self.store[row][0] == self.current_system: self.store[row][13] = self.foreground_color else: self.store[row][13] = None # mark unselectable rows a dirrerent color if self.store[row][0] in self.selection_mask: self.store[row][12] = self.unselectable_color # This is for adding a filename path after the offsetpage is already loaded. def set_filename(self, filename): self.filename = filename self.reload_offsets() # We read the var file directly # and pull out the info we need # if anything goes wrong we set all the info to 0 def read_file(self): try: g54 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g55 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g56 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g57 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g58 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0] g59_3 = [0, 0, 0, 0, 0, 0, 0, 0, 0] if self.filename == None: return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 if not os.path.exists(self.filename): return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 logfile = open(self.filename, "r").readlines() for line in logfile: temp = line.split() param = int(temp[0]) data = float(temp[1]) if 5229 >= param >= 5221: g54[param - 5221] = data elif 5249 >= param >= 5241: g55[param - 5241] = data elif 5269 >= param >= 5261: g56[param - 5261] = data elif 5289 >= param >= 5281: g57[param - 5281] = data elif 5309 >= param >= 5301: g58[param - 5301] = data elif 5329 >= param >= 5321: g59[param - 5321] = data elif 5349 >= param >= 5341: g59_1[param - 5341] = data elif 5369 >= param >= 5361: g59_2[param - 5361] = data elif 5389 >= param >= 5381: g59_3[param - 5381] = data return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 except: return None, None, None, None, None, None, None, None, None # This allows hiding or showing columns from a text string of columnns # eg list ='ab' # default, all the columns are shown def set_col_visible(self, list, bool): try: for index in range(0, len(list)): colstr = str(list[index]) colnum = "xyzabcuvwt".index(colstr.lower()) name = AXISLIST[colnum + 1] renderer = self.wTree.get_object(name) renderer.set_property('visible', bool) except: pass # hide/show the offset rows from a text string of row ids # eg list ='123' def set_row_visible(self, list, bool): try: for index in range(0, len(list)): rowstr = str(list[index]) rownum = "0123456789abcd".index(rowstr.lower()) self.store[rownum][10] = bool except: pass # This does the units conversion # it just multiplies the two arrays def convert_units(self, v): c = self.conversion return map(lambda x, y: x * y, v, c) # make the cells editable and highlight them def set_editing(self, widget): state = widget.get_active() # stop updates from linuxcnc self.editing_mode = state # highlight editable rows if state: color = self.highlight_color else: color = None # Set rows editable for i in range(1, 13): if not self.store[i][0] in ('G5x', 'Rot', 'G92', 'G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1', 'G59.2', 'G59.3'): continue if self.store[i][0] in self.selection_mask: continue self.store[i][11] = state self.store[i][12] = color self.queue_draw() # When the column is edited this does the work # TODO the edited column does not end up showing the editted number even though linuxcnc # registered the change def col_editted(self, widget, filtered_path, new_text, col): (store_path, ) = self.modelfilter.convert_path_to_child_path(filtered_path) row = store_path axisnum = col - 1 # print "EDITED:", new_text, col, int(filtered_path), row, "axis num:", axisnum def system_to_p(system): convert = { "G54": 1, "G55": 2, "G56": 3, "G57": 4, "G58": 5, "G59": 6, "G59.1": 7, "G59.2": 8, "G59.3": 9 } try: pnum = convert[system] except: pnum = None return pnum # Hack to not edit any rotational offset but Z axis if row == 2 and not col == 3: return # set the text style based on unit type if self.display_units_mm: tmpl = lambda s: self.mm_text_template % s else: tmpl = lambda s: self.imperial_text_template % s # allow 'name' columnn text to be arbitrarily changed if col == 10: self.store[row][14] = new_text return # set the text in the table try: self.store[row][col] = locale.format("%10.4f", locale.atof(new_text)) except: print "offsetpage widget error: unrecognized float input" # make sure we switch to correct units for machine and rotational, row 2, does not get converted try: if not self.display_units_mm == self.program_units and not row == 2: if self.program_units == 1: convert = 25.4 else: convert = 1.0 / 25.4 qualified = float(locale.atof(new_text)) * convert else: qualified = float(locale.atof(new_text)) except: print 'error' # now update linuxcnc to the change try: global lncnc_runnning if lncnc_running: if self.status.task_mode != self.linuxcnc.MODE_MDI: self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() if row == 1: self.cmd.mdi("G10 L2 P0 %s %10.4f" % (self.axisletters[axisnum], qualified)) elif row == 2: if col == 3: self.cmd.mdi("G10 L2 P0 R %10.4f" % (qualified)) elif row == 3: self.cmd.mdi("G92 %s %10.4f" % (self.axisletters[axisnum], qualified)) else: pnum = system_to_p(self.store[row][0]) if not pnum == None: self.cmd.mdi( "G10 L2 P%d %s %10.4f" % (pnum, self.axisletters[axisnum], qualified)) self.cmd.mode(self.linuxcnc.MODE_MANUAL) self.cmd.wait_complete() self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.gstat.emit('reload-display') except: print "offsetpage widget error: MDI call error" self.reload_offsets() # callback to cancel G92 when button pressed def zero_g92(self, widget): # print "zero g92" if lncnc_running: try: if self.status.task_mode != self.linuxcnc.MODE_MDI: self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.cmd.mdi("G92.1") self.cmd.mode(self.linuxcnc.MODE_MANUAL) self.cmd.wait_complete() self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.gstat.emit('reload-display') except: print "MDI error in offsetpage widget -zero G92" # callback to zero rotational offset when button pressed def zero_rot(self, widget): # print "zero rotation offset" if lncnc_running: try: if self.status.task_mode != self.linuxcnc.MODE_MDI: self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.cmd.mdi("G10 L2 P0 R 0") self.cmd.mode(self.linuxcnc.MODE_MANUAL) self.cmd.wait_complete() self.cmd.mode(self.linuxcnc.MODE_MDI) self.cmd.wait_complete() self.gstat.emit('reload-display') except: print "MDI error in offsetpage widget-zero rotational offset" # check for linnuxcnc ON and IDLE which is the only safe time to edit the tool file. # if in editing mode don't update else you can't actually edit def periodic_check(self): convert = ("None", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2", "G59.3") try: self.status.poll() on = self.status.task_state > linuxcnc.STATE_OFF idle = self.status.interp_state == linuxcnc.INTERP_IDLE self.edit_button.set_sensitive(bool(on and idle)) self.current_system = convert[self.status.g5x_index] self.program_units = int(self.status.program_units == 2) if self.display_follows_program: self.display_units_mm = self.program_units global lncnc_running lncnc_running = True except: self.current_system = "G54" lncnc_running = False if self.filename and not self.editing_mode: self.reload_offsets() return True # sets the color when editing is active def set_highlight_color(self, value): self.highlight_color = gtk.gdk.Color(value) # sets the text color of the current system description name def set_foreground_color(self, value): self.foreground_color = gtk.gdk.Color(value) # Allows you to set the text font of all the rows and columns def set_font(self, value): for col, name in enumerate(AXISLIST): if col > 10: break temp = self.wTree.get_object("cell_" + name) temp.set_property('font', value) # helper function to set the units to inch def set_to_inch(self): self.display_units_mm = 0 # helper function to set the units to mm def set_to_mm(self): self.display_units_mm = 1 def set_display_follows_program_units(self): self.display_follows_program = True def set_display_independent_units(self): self.display_follows_program = False # helper function to hide control buttons def hide_buttonbox(self, state): if state: self.buttonbox.hide() else: self.buttonbox.show() # Mark the active system with cursor highlight def mark_active(self, system): try: pathlist = [] for row in self.modelfilter: if row[0] == system: pathlist.append(row.path) if len(pathlist) == 1: self.selection.select_path(pathlist[0]) except: print "offsetpage_widget error: cannot select coordinate system", system # Get the selected row the user clicked def get_selected(self): model, iter = self.selection.get_selected() if iter: system = model.get_value(iter, 0) name = model.get_value(iter, 14) # print "System:%s Name:%s"% (system,name) return system, name else: return None, None def on_selection_changed(self, treeselection): system, name = self.get_selected() # print self.status.g5x_index if system in self.selection_mask: self.mark_active(self.current_system) self.emit("selection_changed", system, name) def set_names(self, names): for offset, name in names: for row in range(0, 13): if offset == self.store[row][0]: self.store[row][14] = name def get_names(self): temp = [] for row in range(0, 13): temp.append([self.store[row][0], self.store[row][14]]) return temp # For single click selection when in edit mode def on_treeview2_button_press_event(self, widget, event): if event.button == 1: # left click try: path, model, x, y = widget.get_path_at_pos( int(event.x), int(event.y)) self.view2.set_cursor(path, None, True) except: pass # standard Gobject method def do_get_property(self, property): name = property.name.replace('-', '_') if name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) # standard Gobject method # This is so that in the Glade editor, you can change the display def do_set_property(self, property, value): name = property.name.replace('-', '_') if name == 'font': try: self.set_font(value) except: pass if name == 'hide_columns': self.set_col_visible("xyzabcuvwt", True) self.set_col_visible("%s" % value, False) if name == 'hide_rows': self.set_row_visible("0123456789abc", True) self.set_row_visible("%s" % value, False) if name in self.__gproperties.keys(): setattr(self, name, value) # boiler code for variable access def __getitem__(self, item): return getattr(self, item) def __setitem__(self, item, value): return setattr(self, item, value)
import sys, os, subprocess import traceback import warnings import hal from optparse import Option, OptionParser import gtk import gtk.glade import gobject import signal import gladevcp.makepins from gladevcp.gladebuilder import GladeBuilder from gladevcp import xembed from hal_glib import GStat GSTAT = GStat() options = [ Option( '-c', dest='component', metavar='NAME' , help="Set component name to NAME. Default is basename of UI file") , Option( '-d', action='store_true', dest='debug' , help="Enable debug output") , Option( '-g', dest='geometry', default="", help="""Set geometry WIDTHxHEIGHT+XOFFSET+YOFFSET. Values are in pixel units, XOFFSET/YOFFSET is referenced from top left of screen use -g WIDTHxHEIGHT for just setting size or -g +XOFFSET+YOFFSET for just position""") , Option( '-H', dest='halfile', metavar='FILE' , help="execute hal statements from FILE with halcmd after the component is set up and ready") , Option( '-m', dest='maximum', default=False, help="Force panel window to maxumize") , Option( '-r', dest='gtk_rc', default="", help="read custom GTK rc file to set widget style") , Option( '-R', dest='gtk_workaround', action='store_false',default=True, help="disable workaround for GTK bug to properly read ~/.gtkrc-2.0 gtkrc files")
class Combi_DRO(gtk.VBox): ''' Combi_DRO will display an linuxcnc DRO with all three types at ones Combi_DRO = Combi_DRO(joint_number) joint_number is an integer in the range from 0 to 8 where 0 = X, 1 = Y, 2 = Z, etc. ''' __gtype_name__ = 'Combi_DRO' __gproperties__ = { 'joint_number': (gobject.TYPE_INT, 'Joint Number', '0:X 1:Y 2:Z etc', 0, 8, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'actual': (gobject.TYPE_BOOLEAN, 'Actual Position', 'Display Actual or Commanded Position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units': (gobject.TYPE_BOOLEAN, 'Display in metric units', 'Display in metric or not', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'auto_units': (gobject.TYPE_BOOLEAN, 'Change units according gcode', 'Units will toggle between metric and imperial according to gcode.', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'diameter': (gobject.TYPE_BOOLEAN, 'Diameter Adjustment', 'Display Position As Diameter', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'mm_text_template': (gobject.TYPE_STRING, 'Text template for Metric Units', 'Text template to display. Python formatting may be used for one variable', "%10.3f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'imperial_text_template': (gobject.TYPE_STRING, 'Text template for Imperial Units', 'Text template to display. Python formatting may be used for one variable', "%9.4f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'homed_color': (gtk.gdk.Color.__gtype__, 'homed color', 'Sets the color of the display when the axis is homed', gobject.PARAM_READWRITE), 'unhomed_color': (gtk.gdk.Color.__gtype__, 'unhomed color', 'Sets the color of the display when the axis is not homed', gobject.PARAM_READWRITE), 'abs_color': (gtk.gdk.Color.__gtype__, 'Absolute color', 'Sets the color of the display when absolute coordinates are used', gobject.PARAM_READWRITE), 'rel_color': (gtk.gdk.Color.__gtype__, 'Relative color', 'Sets the color of the display when relative coordinates are used', gobject.PARAM_READWRITE), 'dtg_color': (gtk.gdk.Color.__gtype__, 'DTG color', 'Sets the color of the display when dtg coordinates are used', gobject.PARAM_READWRITE), 'font_size': (gobject.TYPE_INT, 'Font Size', 'The font size of the big numbers, the small ones will be 2.5 times smaler', 8, 96, 25, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'toggle_readout': (gobject.TYPE_BOOLEAN, 'Enable toggling readout with click', 'The DRO will toggle between Absolut , Relativ and DTG with each mouse click.', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'cycle_time': (gobject.TYPE_INT, 'Cycle Time', 'Time, in milliseconds, that display will sleep between polls', 100, 1000, 150, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)), 'units_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN, )), 'system_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )), 'axis_clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )), 'exit': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), } # Init the class def __init__(self, joint_number=0): super(Combi_DRO, self).__init__() # we have to distinguish this, as we use the joints number to check homing # and we do need the axis to check for the positions # this is needed if non trivial kinematics are used or just a lathe, # as the lathe has only two joints, but Z will be the third value in position feedback self.axis_no = self.joint_no = joint_number # get the necessary connections to linuxcnc self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.gstat = GStat() # set some default values' self._ORDER = ["Rel", "Abs", "DTG"] self.system = "Rel" self.homed = False self.homed_color = gtk.gdk.Color("green") self.unhomed_color = gtk.gdk.Color("red") self.abs_color = gtk.gdk.Color("blue") self.rel_color = gtk.gdk.Color("black") self.dtg_color = gtk.gdk.Color("yellow") self.mm_text_template = "%10.3f" self.imperial_text_template = "%9.4f" self.font_size = 25 self.metric_units = True self.machine_units = _MM self.unit_convert = 1 self._auto_units = True self.toggle_readout = True self.cycle_time = 150 # Make the GUI and connect signals self.eventbox = gtk.EventBox() self.eventbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) self.add(self.eventbox) vbox_main = gtk.VBox(False, 0) self.eventbox.add(vbox_main) hbox_up = gtk.HBox(False, 0) vbox_main.pack_start(hbox_up) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size * 1000, 0, -1), (600, 0, -1)) self.lbl_axisletter = gtk.Label(_AXISLETTERS[self.axis_no]) self.lbl_axisletter.set_attributes(attr) hbox_up.pack_start(self.lbl_axisletter, False, False) vbox_ref_type = gtk.VBox(False, 0) hbox_up.pack_start(vbox_ref_type, False, False) lbl_space = gtk.Label("") vbox_ref_type.pack_start(lbl_space) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_main = gtk.Label(self.system) vbox_ref_type.pack_start(self.lbl_sys_main, False, False) self.lbl_sys_main.set_attributes(attr) self.main_dro = gtk.Label("9999.999") hbox_up.pack_start(self.main_dro) self.main_dro.set_alignment(1.0, 0.5) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size, 0, -1), (600, 0, -1)) self.main_dro.set_attributes(attr) hbox_down = gtk.HBox(False, 5) vbox_main.pack_start(hbox_down) self.lbl_sys_left = gtk.Label("Abs") hbox_down.pack_start(self.lbl_sys_left) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_left.set_attributes(attr) self.dro_left = gtk.Label("-11.111") hbox_down.pack_start(self.dro_left) self.dro_left.set_alignment(1.0, 0.5) self.dro_left.set_attributes(attr) self.lbl_sys_right = gtk.Label("DTG") hbox_down.pack_start(self.lbl_sys_right) self.lbl_sys_right.set_attributes(attr) self.dro_right = gtk.Label("22.222") hbox_down.pack_start(self.dro_right) self.dro_right.set_alignment(1.0, 0.5) self.dro_right.set_attributes(attr) self.eventbox.connect("button_press_event", self._on_eventbox_clicked) self.show_all() self.gstat.connect('not-all-homed', self._not_all_homed) self.gstat.connect('all-homed', self._all_homed) self.gstat.connect('homed', self._homed) # This try is only needed because while working with glade # linuxcnc may not be working try: self.inifile = self.linuxcnc.ini(INIPATH) # check the ini file if UNITS are set to mm" # first check the global settings units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: # else then the X axis units units = self.inifile.find("AXIS_0", "UNITS") except: units = "inch" if units == "mm" or units == "metric" or units == "1.0": self.machine_units = _MM else: self.machine_units = _INCH # add the timer at a period of 100 ms gobject.timeout_add(self.cycle_time, self._periodic) # make an pango attribute to be used with several labels def _set_attributes(self, bgcolor, fgcolor, size, weight): attr = pango.AttrList() bg_color = pango.AttrBackground(bgcolor[0], bgcolor[1], bgcolor[2], 0, -1) attr.insert(bg_color) size_attr = pango.AttrSize(size[0], size[1], size[2]) attr.insert(size_attr) weight_attr = pango.AttrWeight(weight[0], weight[1], weight[2]) attr.insert(weight_attr) fg_color = pango.AttrForeground(fgcolor[0], fgcolor[1], fgcolor[2], 0, 13) attr.insert(fg_color) return attr # if the eventbox has been clicked, we like to toggle the DRO's # or just emit a signal to allow GUI to do what ever they want with that # signal- gmoccapy uses this signal to open the touch off dialog def _on_eventbox_clicked(self, widget, event): if event.x <= self.lbl_axisletter.get_allocation( ).width + self.lbl_sys_main.get_allocation().width: self.emit('axis_clicked', self.lbl_axisletter.get_text().lower()) else: if not self.toggle_readout: return self.toogle_readout() # Get propertys def do_get_property(self, property): name = property.name.replace('-', '_') if name in list(self.__gproperties.keys()): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) # Set propertys def do_set_property(self, property, value): try: name = property.name.replace('-', '_') if name in list(self.__gproperties.keys()): setattr(self, name, value) self.queue_draw() if name in ('mm_text_template', 'imperial_text_template'): try: v = value % 0.0 except Exception as e: print("Invalid format string '%s': %s" % (value, e)) return False if name == "homed_color": self.homed_color = value self._set_labels() if name == "unhomed_color": self.unhomed_color = value self._set_labels() if name == "abs_color": self.abs_color = value self._set_labels() if name == "rel_color": self.rel_color = value self._set_labels() if name == "dtg_color": self.dtg_color = value self._set_labels() if name == "auto_units": self._auto_units = value self._set_labels() if name == "joint_number": self.axis_no = self.joint = value self.change_axisletter(_AXISLETTERS[self.axis_no]) if name == "font_size": self.font_size = value self._set_labels() if name == "toggle_readout": self.toggle_readout = value if name == "cycle_time": self.cycle_time = value if name in ('metric_units', 'actual', 'diameter'): setattr(self, name, value) self.queue_draw() else: raise AttributeError('unknown property %s' % property.name) except: pass # get the actual coordinate system to display it on the DRO def _get_current_system(self): gcode = self.status.gcodes[1:] for code in gcode: if code >= 540 and code <= 590: return "G%s" % (code / 10) elif code > 590 and code <= 593: return "G%s" % (code / 10.0) return "Rel" # Get the units used according to gcode def _get_current_units(self): gcode = self.status.gcodes[1:] for code in gcode: if code >= 200 and code <= 210: return (code / 10) return False # update the labels def _set_labels(self): if self._ORDER[0] == "Rel": self.lbl_sys_main.set_text(self._get_current_system()) else: self.lbl_sys_main.set_text(self._ORDER[0]) if self._ORDER[1] == "Rel": self.lbl_sys_left.set_text(self._get_current_system()) else: self.lbl_sys_left.set_text(self._ORDER[1]) if self._ORDER[2] == "Rel": self.lbl_sys_right.set_text(self._get_current_system()) else: self.lbl_sys_right.set_text(self._ORDER[2]) if self._ORDER[0] == "Abs": bg_color = self.abs_color elif self._ORDER[0] == "DTG": bg_color = self.dtg_color else: bg_color = self.rel_color self.eventbox.modify_bg(gtk.STATE_NORMAL, bg_color) bg_color = self._convert_to_rgb(bg_color) if self.homed: fg_color = self.homed_color else: fg_color = self.unhomed_color fg_color = self._convert_to_rgb(fg_color) attr = self._set_attributes(bg_color, fg_color, (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_main.set_attributes(attr) self.lbl_sys_left.set_attributes(attr) self.lbl_sys_right.set_attributes(attr) self.dro_left.set_attributes(attr) self.dro_right.set_attributes(attr) attr = self._set_attributes(bg_color, fg_color, (self.font_size * 1000, 0, -1), (600, 0, -1)) self.main_dro.set_attributes(attr) self.lbl_axisletter.set_attributes(attr) self.system = self._get_current_system() # returns the separate RGB color numbers from the color widget def _convert_to_rgb(self, spec): color = spec.to_string() temp = color.strip("#") r = temp[0:4] g = temp[4:8] b = temp[8:] return (int(r, 16), int(g, 16), int(b, 16)) # periodic call to update the positions, every 100 ms def _periodic(self): # we do not want to throw errors if linuxcnc has been killed # from external command try: self.status.poll() except: pass if self.status.kinematics_type != linuxcnc.KINEMATICS_IDENTITY and not self.homed: self.main_dro.set_text("----.---") self.dro_left.set_text("----.---") self.dro_right.set_text("----.---") return True try: main, left, right = self._position() if self.system != self._get_current_system(): self._set_labels() self.emit("system_changed", self._get_current_system()) if (self._get_current_units() == 20 and self.metric_units) or (self._get_current_units() == 21 and not self.metric_units): if self._auto_units: self.metric_units = not self.metric_units self.emit("units_changed", self.metric_units) except: sys = 0 main = 9999.999 left = 10.123 right = 0.000 if self.metric_units: tmpl = lambda s: self.mm_text_template % s else: tmpl = lambda s: self.imperial_text_template % s if self.diameter: scale = 2.0 else: scale = 1.0 main_dro = tmpl(main * scale) left_dro = tmpl(left * scale) right_dro = tmpl(right * scale) self.main_dro.set_text(main_dro) self.dro_left.set_text(left_dro) self.dro_right.set_text(right_dro) return True # calculate the positions to display def _position(self): if self.actual: p = self.status.actual_position else: p = self.status.position dtg = self.status.dtg[self.axis_no] abs_pos = p[self.axis_no] rel_pos = p[self.axis_no] - self.status.g5x_offset[ self.axis_no] - self.status.tool_offset[self.axis_no] if self.status.rotation_xy != 0: t = math.radians(-self.status.rotation_xy) x = p[0] - self.status.g5x_offset[0] - self.status.tool_offset[0] y = p[1] - self.status.g5x_offset[1] - self.status.tool_offset[1] if self.axis_no == 0: rel_pos = x * math.cos(t) - y * math.sin(t) if self.axis_no == 1: rel_pos = x * math.sin(t) + y * math.cos(t) rel_pos -= self.status.g92_offset[self.axis_no] if self.metric_units and self.machine_units == _INCH: if self.axis_no not in (3, 4, 5): abs_pos = abs_pos * 25.4 rel_pos = rel_pos * 25.4 dtg = dtg * 25.4 if not self.metric_units and self.machine_units == _MM: if self.axis_no not in (3, 4, 5): abs_pos = abs_pos / 25.4 rel_pos = rel_pos / 25.4 dtg = dtg / 25.4 if self._ORDER == ["Rel", "Abs", "DTG"]: return rel_pos, abs_pos, dtg if self._ORDER == ["DTG", "Rel", "Abs"]: return dtg, rel_pos, abs_pos if self._ORDER == ["Abs", "DTG", "Rel"]: return abs_pos, dtg, rel_pos def _not_all_homed(self, widget, data=None): if self.status.kinematics_type == linuxcnc.KINEMATICS_IDENTITY: self.status.poll() self.homed = self.status.homed[self.joint_no] else: self.homed = False self._set_labels() def _all_homed(self, widget, data=None): print("Combi DRO all homed") if self.status.kinematics_type == linuxcnc.KINEMATICS_IDENTITY: return if not self.homed: self.homed = True self._set_labels() def _homed(self, widget, data=None): if self.status.kinematics_type != linuxcnc.KINEMATICS_IDENTITY: return else: self.status.poll() self.homed = self.status.homed[self.joint_no] self._set_labels() # sets the DRO explicitly to inch or mm # attentions auto_units also takes effect on that! def set_to_inch(self, state): ''' sets the DRO to show imperial units Combi_DRO.set_to_inch(state) state = boolean (true or False) ''' if state: self.metric_units = False else: self.metric_units = True # If auto_units is true, the DRO will change according to the # active gcode (G20 / G21) def set_auto_units(self, state): ''' if True the DRO will change units according to active gcode (G20 / G21) Combi_DRO.set_auto_units(state) state = boolean (true or False) ''' self._auto_units = state # Set the axis to diameter mode, the DRO value will be # multiplied by 2 def set_to_diameter(self, state): ''' if True the DRO will show the diameter not the radius, specially needed for lathes the DRO value will be multiplied by 2 Combi_DRO.set_to_diameter(state) state = boolean (true or False) ''' self.diameter = state # this will toggle the DRO around, mainly used to maintain all DRO # at the same state, because a click on one will only change that DRO # This can be used to change also the others def toogle_readout(self): ''' toggles the order of the DRO in the widget Combi_DRO.toggle_readout() ''' self._ORDER = [self._ORDER[2], self._ORDER[0], self._ORDER[1]] self._set_labels() self.emit("clicked", self.joint_number, self._ORDER) # You can change the automatic given axisletter using this function # i.e. to use an axis as R or D insteadt of X on a lathe def change_axisletter(self, letter): ''' changes the automatically given axis-letter very useful to change an lathe DRO from X to R or D Combi_DRO.change_axis-letter(letter) letter = string ''' self.lbl_axisletter.set_text(letter) def set_joint_no(self, joint): ''' changes the joint, not the joint number. This is handy for special cases, like Gantry configs, i.e. XYYZ, where joint 0 = X, joint 1 = Y1 joint 2 = Y2 and joint 3 = Z, so the Z axis can be set to joint_number 2 giving the axis letter Z and joint 3 being in this case the corresponding joint, joint 3 instead of 2 ''' self.joint_no = joint def set_axis(self, axis): ''' changes the axis, not the joint number. This is handy for special cases, like Lathe configs, i.e. XZ, where joint 0 = X, joint 1 = Z so the Z axis must be set to joint_number 1 for homing, but we need the axis letter Z to give the correct position feedback ''' self.axis_no = "xyzabcuvws".index(axis.lower()) # returns the order of the DRO, mainly used to maintain them consistent # the order will also be transmitted with the clicked signal def get_order(self): ''' returns the order of the DRO in the widget mainly used to maintain them consistent the order will also be transmitted with the clicked signal Combi_DRO.get_order() returns a list containing the order ''' return self._ORDER # sets the order of the DRO, mainly used to maintain them consistent def set_order(self, order): ''' sets the order of the DRO, mainly used to maintain them consistent Combi_DRO.set_order(order) order = list object, must be one of ["Rel", "Abs", "DTG"] ["DTG", "Rel", "Abs"] ["Abs", "DTG", "Rel"] ''' self._ORDER = order self._set_labels() # This will return the position information of all three DRO # it will be in the order Abs, Rel, DTG def get_position(self): ''' returns the positions of the DRO Combi_DRO.get_position() returns the position of the DRO as a list of floats the order is independent of the order shown on the DRO and will be givven as [Absolute , relative , DTG] Absolute = the machine coordinates, depends on the actual property will give actual or commanded position Relative = will be the coordinates of the actual coordinate system DTG = the distance to go, will mosltly be 0, as this function should not be used while the machine is moving, because of time delays ''' positions = self._position() if self._ORDER == ["Rel", "Abs", "DTG"]: return positions[1], positions[0], positions[2] if self._ORDER == ["DTG", "Rel", "Abs"]: return positions[2], positions[1], positions[0] if self._ORDER == ["Abs", "DTG", "Rel"]: return positions[0], positions[2], positions[1]
def __init__(self, joint_number = 0): super(Combi_DRO, self).__init__() # get the necessary connections to linuxcnc self.joint_number = self.joint = joint_number self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.gstat = GStat() self.get_ini_info = getiniinfo.GetIniInfo() # set some default values' self._ORDER = ["Rel", "Abs", "DTG"] self.system = "Rel" self.homed = False self.homed_color = gtk.gdk.Color("green") self.unhomed_color = gtk.gdk.Color("red") self.abs_color = gtk.gdk.Color("blue") self.rel_color = gtk.gdk.Color("black") self.dtg_color = gtk.gdk.Color("yellow") self.mm_text_template = "%10.3f" self.imperial_text_template = "%9.4f" self.font_size = 25 self.metric_units = True self.machine_units = _MM self.unit_convert = 1 self._auto_units = True self.toggle_readout = True self.cycle_time = 150 # Make the GUI and connect signals self.eventbox = gtk.EventBox() self.eventbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) self.add(self.eventbox) vbox_main = gtk.VBox(False, 0) self.eventbox.add(vbox_main) hbox_up = gtk.HBox(False, 0) vbox_main.pack_start(hbox_up) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size * 1000, 0, -1), (600, 0, -1)) self.lbl_axisletter = gtk.Label(_AXISLETTERS[self.joint_number]) self.lbl_axisletter.set_attributes(attr) hbox_up.pack_start(self.lbl_axisletter, False, False) vbox_ref_type = gtk.VBox(False, 0) hbox_up.pack_start(vbox_ref_type, False, False) lbl_space = gtk.Label("") vbox_ref_type.pack_start(lbl_space) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_main = gtk.Label(self.system) vbox_ref_type.pack_start(self.lbl_sys_main, False, False) self.lbl_sys_main.set_attributes(attr) self.main_dro = gtk.Label("9999.999") hbox_up.pack_start(self.main_dro) self.main_dro.set_alignment(1.0, 0.5) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size, 0, -1), (600, 0, -1)) self.main_dro.set_attributes(attr) hbox_down = gtk.HBox(False, 5) vbox_main.pack_start(hbox_down) self.lbl_sys_left = gtk.Label("Abs") hbox_down.pack_start(self.lbl_sys_left) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_left.set_attributes(attr) self.dro_left = gtk.Label("-11.111") hbox_down.pack_start(self.dro_left) self.dro_left.set_alignment(1.0, 0.5) self.dro_left.set_attributes(attr) self.lbl_sys_right = gtk.Label("DTG") hbox_down.pack_start(self.lbl_sys_right) self.lbl_sys_right.set_attributes(attr) self.dro_right = gtk.Label("22.222") hbox_down.pack_start(self.dro_right) self.dro_right.set_alignment(1.0, 0.5) self.dro_right.set_attributes(attr) self.eventbox.connect("button_press_event", self._on_eventbox_clicked) self.show_all() self.gstat.connect('not-all-homed', self._not_all_homed ) self.gstat.connect('all-homed', self._all_homed ) self.gstat.connect('homed', self._homed ) # This try is only needed because while working with glade # linuxcnc may not be working try: self.inifile = self.linuxcnc.ini(INIPATH) # check the ini file if UNITS are set to mm" # first check the global settings units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: # else then the X axis units units = self.inifile.find("AXIS_0", "UNITS") except: units = "inch" if units == "mm" or units == "metric" or units == "1.0": self.machine_units = _MM else: self.machine_units = _INCH # add the timer at a period of 100 ms gobject.timeout_add(self.cycle_time, self._periodic)
class Combi_DRO(gtk.VBox): ''' Combi_DRO will display an linuxcnc DRO with all three types at ones Combi_DRO = Combi_DRO(joint_number) joint_number is an integer in the range from 0 to 8 where 0 = X, 1 = Y, 2 = Z, etc. ''' __gtype_name__ = 'Combi_DRO' __gproperties__ = { 'joint_number' : (gobject.TYPE_INT, 'Joint Number', '0:X 1:Y 2:Z etc', 0, 8, 0, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'actual' : (gobject.TYPE_BOOLEAN, 'Actual Position', 'Display Actual or Commanded Position', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'metric_units' : (gobject.TYPE_BOOLEAN, 'Display in metric units', 'Display in metric or not', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'auto_units' : (gobject.TYPE_BOOLEAN, 'Change units according gcode', 'Units will toggle between metric and imperial according to gcode.', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'diameter' : (gobject.TYPE_BOOLEAN, 'Diameter Adjustment', 'Display Position As Diameter', False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'mm_text_template' : (gobject.TYPE_STRING, 'Text template for Metric Units', 'Text template to display. Python formatting may be used for one variable', "%10.3f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'imperial_text_template' : (gobject.TYPE_STRING, 'Text template for Imperial Units', 'Text template to display. Python formatting may be used for one variable', "%9.4f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'homed_color' : (gtk.gdk.Color.__gtype__, 'homed color', 'Sets the color of the display when the axis is homed', gobject.PARAM_READWRITE), 'unhomed_color' : (gtk.gdk.Color.__gtype__, 'unhomed color', 'Sets the color of the display when the axis is not homed', gobject.PARAM_READWRITE), 'abs_color' : (gtk.gdk.Color.__gtype__, 'Absolute color', 'Sets the color of the display when absolute coordinates are used', gobject.PARAM_READWRITE), 'rel_color' : (gtk.gdk.Color.__gtype__, 'Relative color', 'Sets the color of the display when relative coordinates are used', gobject.PARAM_READWRITE), 'dtg_color' : (gtk.gdk.Color.__gtype__, 'DTG color', 'Sets the color of the display when dtg coordinates are used', gobject.PARAM_READWRITE), 'font_size' : (gobject.TYPE_INT, 'Font Size', 'The font size of the big numbers, the small ones will be 2.5 times smaler', 8, 96, 25, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'toggle_readout' : (gobject.TYPE_BOOLEAN, 'Enable toggling readout with click', 'The DRO will toggle between Absolut , Relativ and DTG with each mouse click.', True, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), 'cycle_time' : (gobject.TYPE_INT, 'Cycle Time', 'Time, in milliseconds, that display will sleep between polls', 100, 1000, 150, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT), } __gproperties = __gproperties__ __gsignals__ = { 'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)), 'units_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN,)), 'system_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 'exit': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), } # Init the class def __init__(self, joint_number = 0): super(Combi_DRO, self).__init__() # get the necessary connections to linuxcnc self.joint_number = self.joint = joint_number self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.gstat = GStat() # set some default values' self._ORDER = ["Rel", "Abs", "DTG"] self.system = "Rel" self.homed = False self.homed_color = gtk.gdk.Color("green") self.unhomed_color = gtk.gdk.Color("red") self.abs_color = gtk.gdk.Color("blue") self.rel_color = gtk.gdk.Color("black") self.dtg_color = gtk.gdk.Color("yellow") self.mm_text_template = "%10.3f" self.imperial_text_template = "%9.4f" self.font_size = 25 self.metric_units = True self.machine_units = _MM self.unit_convert = 1 self._auto_units = True self.toggle_readout = True self.cycle_time = 150 # Make the GUI and connect signals self.eventbox = gtk.EventBox() self.eventbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) self.add(self.eventbox) vbox_main = gtk.VBox(False, 0) self.eventbox.add(vbox_main) hbox_up = gtk.HBox(False, 0) vbox_main.pack_start(hbox_up) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size * 1000, 0, -1), (600, 0, -1)) self.lbl_axisletter = gtk.Label(_AXISLETTERS[self.joint_number]) self.lbl_axisletter.set_attributes(attr) hbox_up.pack_start(self.lbl_axisletter, False, False) vbox_ref_type = gtk.VBox(False, 0) hbox_up.pack_start(vbox_ref_type, False, False) lbl_space = gtk.Label("") vbox_ref_type.pack_start(lbl_space) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_main = gtk.Label(self.system) vbox_ref_type.pack_start(self.lbl_sys_main, False, False) self.lbl_sys_main.set_attributes(attr) self.main_dro = gtk.Label("9999.999") hbox_up.pack_start(self.main_dro) self.main_dro.set_alignment(1.0, 0.5) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size, 0, -1), (600, 0, -1)) self.main_dro.set_attributes(attr) hbox_down = gtk.HBox(False, 5) vbox_main.pack_start(hbox_down) self.lbl_sys_left = gtk.Label("Abs") hbox_down.pack_start(self.lbl_sys_left) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_left.set_attributes(attr) self.dro_left = gtk.Label("-11.111") hbox_down.pack_start(self.dro_left) self.dro_left.set_alignment(1.0, 0.5) self.dro_left.set_attributes(attr) self.lbl_sys_right = gtk.Label("DTG") hbox_down.pack_start(self.lbl_sys_right) self.lbl_sys_right.set_attributes(attr) self.dro_right = gtk.Label("22.222") hbox_down.pack_start(self.dro_right) self.dro_right.set_alignment(1.0, 0.5) self.dro_right.set_attributes(attr) self.eventbox.connect("button_press_event", self._on_eventbox_clicked) self.show_all() self.gstat.connect('not-all-homed', self._not_all_homed ) self.gstat.connect('all-homed', self._all_homed ) self.gstat.connect('homed', self._homed ) # This try is only needed because while working with glade # linuxcnc may not be working try: self.inifile = self.linuxcnc.ini(INIPATH) # check the ini file if UNITS are set to mm" # first check the global settings units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: # else then the X axis units units = self.inifile.find("AXIS_0", "UNITS") except: units = "inch" if units == "mm" or units == "metric" or units == "1.0": self.machine_units = _MM else: self.machine_units = _INCH # add the timer at a period of 100 ms gobject.timeout_add(self.cycle_time, self._periodic) # make an pango attribute to be used with several labels def _set_attributes(self, bgcolor, fgcolor, size, weight): attr = pango.AttrList() bg_color = pango.AttrBackground(bgcolor[0], bgcolor[1], bgcolor[2], 0, -1) attr.insert(bg_color) size_attr = pango.AttrSize(size[0], size[1], size[2]) attr.insert(size_attr) weight_attr = pango.AttrWeight(weight[0], weight[1], weight[2]) attr.insert(weight_attr) fg_color = pango.AttrForeground(fgcolor[0], fgcolor[1], fgcolor[2], 0, 13) attr.insert(fg_color) return attr # if the eventbox has been clicked, we like to toggle the DRO's def _on_eventbox_clicked(self, widget, event): if not self.toggle_readout: return self.toogle_readout() # Get propertys def do_get_property(self, property): name = property.name.replace('-', '_') if name in self.__gproperties.keys(): return getattr(self, name) else: raise AttributeError('unknown property %s' % property.name) # Set propertys def do_set_property(self, property, value): try: name = property.name.replace('-', '_') if name in self.__gproperties.keys(): setattr(self, name, value) self.queue_draw() if name in ('mm_text_template', 'imperial_text_template'): try: v = value % 0.0 except Exception, e: print "Invalid format string '%s': %s" % (value, e) return False if name == "homed_color": self.homed_color = value self._set_labels() if name == "unhomed_color": self.unhomed_color = value self._set_labels() if name == "abs_color": self.abs_color = value self._set_labels() if name == "rel_color": self.rel_color = value self._set_labels() if name == "dtg_color": self.dtg_color = value self._set_labels() if name == "auto_units": self._auto_units = value self._set_labels() if name == "joint_number": self.joint_number = self.joint = value self.change_axisletter(_AXISLETTERS[self.joint_number]) if name == "font_size": self.font_size = value self._set_labels() if name == "toggle_readout": self.toggle_readout = value if name == "cycle_time": self.cycle_time = value if name in ('metric_units', 'actual', 'diameter'): setattr(self, name, value) self.queue_draw() else:
def __init__(self, filename=None, *a, **kw): super(OffsetPage, self).__init__() self.gstat = GStat() self.filename = filename self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.cmd = linuxcnc.command() self.hash_check = None self.display_units_mm = 0 # imperial self.machine_units_mm = 0 # imperial self.program_units = 0 # imperial self.display_follows_program = False # display units are chosen indepenadently of G20/G21 self.font = "sans 12" self.editing_mode = False self.highlight_color = gtk.gdk.Color("lightblue") self.foreground_color = gtk.gdk.Color("red") self.unselectable_color = gtk.gdk.Color("lightgray") self.hidejointslist = [] self.hidecollist = [] self.wTree = gtk.Builder() self.wTree.set_translation_domain( "linuxcnc") # for locale translations self.wTree.add_from_file(os.path.join(datadir, "offsetpage.glade")) self.current_system = None self.selection_mask = () self.axisletters = ["x", "y", "z", "a", "b", "c", "u", "v", "w"] # global references self.store = self.wTree.get_object("liststore2") self.all_window = self.wTree.get_object("all_window") self.view2 = self.wTree.get_object("treeview2") self.view2.connect('button_press_event', self.on_treeview2_button_press_event) self.selection = self.view2.get_selection() self.selection.set_mode(gtk.SELECTION_SINGLE) self.selection.connect("changed", self.on_selection_changed) self.modelfilter = self.wTree.get_object("modelfilter") self.edit_button = self.wTree.get_object("edit_button") self.edit_button.connect('toggled', self.set_editing) zero_g92_button = self.wTree.get_object("zero_g92_button") zero_g92_button.connect('clicked', self.zero_g92) zero_rot_button = self.wTree.get_object("zero_rot_button") zero_rot_button.connect('clicked', self.zero_rot) self.set_font(self.font) self.modelfilter.set_visible_column(10) self.buttonbox = self.wTree.get_object("buttonbox") for col, name in enumerate(AXISLIST): if col > 9: break temp = self.wTree.get_object("cell_%s" % name) temp.connect('edited', self.col_editted, col) temp = self.wTree.get_object("cell_name") temp.connect('edited', self.col_editted, 10) # reparent offsetpage box from Glades top level window to widgets VBox window = self.wTree.get_object("offsetpage_box") window.reparent(self) # check the ini file if UNITS are set to mm # first check the global settings # if not available then the X axis units try: self.inifile = self.linuxcnc.ini(INIPATH) units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: units = self.inifile.find("AXIS_X", "UNITS") except: print "**** Offsetpage widget ERROR: LINEAR_UNITS not found in INI's TRAJ section" units = "inch" # now setup the conversion array depending on the machine native units if units == "mm" or units == "metric" or units == "1.0": self.machine_units_mm = 1 self.conversion = [1.0 / 25.4] * 3 + [1] * 3 + [1.0 / 25.4] * 3 else: self.machine_units_mm = 0 self.conversion = [25.4] * 3 + [1] * 3 + [25.4] * 3 # check linuxcnc status every half second gobject.timeout_add(500, self.periodic_check)
def __init__(self, joint_number = 0): super(Combi_DRO, self).__init__() # get the necessary connections to linuxcnc self.joint_number = self.joint = joint_number self.linuxcnc = linuxcnc self.status = linuxcnc.stat() self.gstat = GStat() # set some default values' self._ORDER = ["Rel", "Abs", "DTG"] self.system = "Rel" self.homed = False self.homed_color = gtk.gdk.Color("green") self.unhomed_color = gtk.gdk.Color("red") self.abs_color = gtk.gdk.Color("blue") self.rel_color = gtk.gdk.Color("black") self.dtg_color = gtk.gdk.Color("yellow") self.mm_text_template = "%10.3f" self.imperial_text_template = "%9.4f" self.font_size = 25 self.metric_units = True self.machine_units = _MM self.unit_convert = 1 self._auto_units = True self.toggle_readout = True self.cycle_time = 150 # Make the GUI and connect signals self.eventbox = gtk.EventBox() self.eventbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) self.add(self.eventbox) vbox_main = gtk.VBox(False, 0) self.eventbox.add(vbox_main) hbox_up = gtk.HBox(False, 0) vbox_main.pack_start(hbox_up) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size * 1000, 0, -1), (600, 0, -1)) self.lbl_axisletter = gtk.Label(_AXISLETTERS[self.joint_number]) self.lbl_axisletter.set_attributes(attr) hbox_up.pack_start(self.lbl_axisletter, False, False) vbox_ref_type = gtk.VBox(False, 0) hbox_up.pack_start(vbox_ref_type, False, False) lbl_space = gtk.Label("") vbox_ref_type.pack_start(lbl_space) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_main = gtk.Label(self.system) vbox_ref_type.pack_start(self.lbl_sys_main, False, False) self.lbl_sys_main.set_attributes(attr) self.main_dro = gtk.Label("9999.999") hbox_up.pack_start(self.main_dro) self.main_dro.set_alignment(1.0, 0.5) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (self.font_size, 0, -1), (600, 0, -1)) self.main_dro.set_attributes(attr) hbox_down = gtk.HBox(False, 5) vbox_main.pack_start(hbox_down) self.lbl_sys_left = gtk.Label("Abs") hbox_down.pack_start(self.lbl_sys_left) attr = self._set_attributes((0, 0, 0), (65535, 0, 0), (int(self.font_size * 1000 / 2.5), 0, -1), (600, 0, -1)) self.lbl_sys_left.set_attributes(attr) self.dro_left = gtk.Label("-11.111") hbox_down.pack_start(self.dro_left) self.dro_left.set_alignment(1.0, 0.5) self.dro_left.set_attributes(attr) self.lbl_sys_right = gtk.Label("DTG") hbox_down.pack_start(self.lbl_sys_right) self.lbl_sys_right.set_attributes(attr) self.dro_right = gtk.Label("22.222") hbox_down.pack_start(self.dro_right) self.dro_right.set_alignment(1.0, 0.5) self.dro_right.set_attributes(attr) self.eventbox.connect("button_press_event", self._on_eventbox_clicked) self.show_all() self.gstat.connect('not-all-homed', self._not_all_homed ) self.gstat.connect('all-homed', self._all_homed ) self.gstat.connect('homed', self._homed ) # This try is only needed because while working with glade # linuxcnc may not be working try: self.inifile = self.linuxcnc.ini(INIPATH) # check the ini file if UNITS are set to mm" # first check the global settings units = self.inifile.find("TRAJ", "LINEAR_UNITS") if units == None: # else then the X axis units units = self.inifile.find("AXIS_0", "UNITS") except: units = "inch" if units == "mm" or units == "metric" or units == "1.0": self.machine_units = _MM else: self.machine_units = _INCH # add the timer at a period of 100 ms gobject.timeout_add(self.cycle_time, self._periodic)