#!/usr/bin/python2.4 # Gscreen a GUI for linuxcnc cnc controller # Chris Morley copyright 2012 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Gscreen is made for running linuxcnc CNC machines # currently only machines with XYZA or less are useable. # Gscreen was built with touchscreens in mind though a mouse works too. # a keyboard is necessary for editting gcode # Gscreen is, at it's heart, a gladevcp program though loaded in a non standard way. # one can also use a second monitor to display a second glade panel # this would probably be most useful for user's custom status widgets. # you would need to calibrate your touchscreen to just work on a single screen import pygtk pygtk.require("2.0") import gtk import gtk.glade import gobject import hal import sys,os,subprocess from optparse import Option, OptionParser import gladevcp.makepins from gladevcp.gladebuilder import GladeBuilder import pango import traceback import atexit import vte import time from time import strftime,localtime import hal_glib # try to add a notify system so messages use the # nice intergrated pop-ups # Ubuntu kinda wrecks this be not following the # standard - you can't set how long the message stays up for. # I suggest fixing this with a PPA off the net # https://launchpad.net/~leolik/+archive/leolik?field.series_filter=lucid try: NOTIFY_AVAILABLE = False import pynotify if not pynotify.init("Gscreen"): print "**** GSCREEN INFO: There was a problem initializing the pynotify module" else: NOTIFY_AVAILABLE = True except: print "**** GSCREEN INFO: You don't seem to have pynotify installed" # try to add ability for audio feedback to user. try: _AUDIO_AVAILABLE = False import pygst pygst.require("0.10") import gst _AUDIO_AVAILABLE = True print "**** GSCREEN INFO: audio available!" except: print "**** GSCREEN INFO: no audio alerts available - PYGST libray not installed?" # BASE is the absolute path to linuxcnc base # libdir is the path to Gscreen python files # datadir is where the standarad GLADE files are # imagedir is for icons # themesdir is path to system's GTK2 theme folder BASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..")) libdir = os.path.join(BASE, "lib", "python") datadir = os.path.join(BASE, "share", "linuxcnc") imagedir = os.path.join(BASE, "share","gscreen","images") SKINPATH = os.path.join(BASE, "share","gscreen","skins") sys.path.insert(0, libdir) themedir = "/usr/share/themes" xmlname = os.path.join(datadir,"gscreen.glade") xmlname2 = os.path.join(datadir,"gscreen2.glade") ALERT_ICON = os.path.join(imagedir,"applet-critical.png") INFO_ICON = os.path.join(imagedir,"std_info.gif") # internationalization and localization import locale, gettext # path to TCL for external programs eg. halshow TCLPATH = os.environ['LINUXCNC_TCL_DIR'] # path to the configuration the user requested # used to see if the is local GLADE files to use CONFIGPATH = os.environ['CONFIG_DIR'] import linuxcnc from gscreen import emc_interface from gscreen import mdi from gscreen import preferences from gscreen import keybindings # this is for hiding the pointer when using a touch screen pixmap = gtk.gdk.Pixmap(None, 1, 1, 1) color = gtk.gdk.Color() INVISABLE = gtk.gdk.Cursor(pixmap, pixmap, color, color, 0, 0) # to help with debugging new screens verbose_debug = False # print debug messages if debug is true gscreen_debug = False def dbg(str): global gscreen_debug if not gscreen_debug: return print str # Throws up a dialog with debug info when an error is encountered def excepthook(exc_type, exc_obj, exc_tb): try: w = app.widgets.window1 except KeyboardInterrupt: sys.exit(0) except NameError: w = None lines = traceback.format_exception(exc_type, exc_obj, exc_tb) m = gtk.MessageDialog(w, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, ("Gscreen encountered an error. The following " "information may be useful in troubleshooting:\n\n") + "".join(lines)) m.show() m.run() m.destroy() sys.excepthook = excepthook # constants _X = 0;_Y = 1;_Z = 2;_A = 3;_B = 4;_C = 5;_U = 6;_V = 7;_W = 8 _ABS = 0;_REL = 1;_DTG = 2 _SPINDLE_INPUT = 1;_PERCENT_INPUT = 2;_VELOCITY_INPUT = 3;_DEGREE_INPUT = 4 # the player class does the work of playing the audio hints # http://pygstdocs.berlios.de/pygst-tutorial/introduction.html class Player: def __init__(self): #Element playbin automatic plays any file self.player = gst.element_factory_make("playbin", "player") #Enable message bus to check for errors in the pipeline bus = self.player.get_bus() bus.add_signal_watch() bus.connect("message", self.on_message) self.loop = gobject.MainLoop() def run(self): self.player.set_state(gst.STATE_PLAYING) self.loop.run() def set_sound(self,file): #Set the uri to the file self.player.set_property("uri", "file://" + file) def on_message(self, bus, message): t = message.type if t == gst.MESSAGE_EOS: #file ended, stop self.player.set_state(gst.STATE_NULL) self.loop.quit() elif t == gst.MESSAGE_ERROR: #Error ocurred, print and stop self.player.set_state(gst.STATE_NULL) err, debug = message.parse_error() print "Error: %s" % err, debug self.loop.quit() # a class for holding the glade widgets rather then searching for them each time class Widgets: def __init__(self, xml): self._xml = xml def __getattr__(self, attr): r = self._xml.get_object(attr) if r is None: raise AttributeError, "No widget %r" % attr return r def __getitem__(self, attr): r = self._xml.get_object(attr) if r is None: raise IndexError, "No widget %r" % attr return r # a class for holding data # here we intialize the data class Data: def __init__(self): # constants for mode idenity self._MAN = 0 self._MDI = 1 self._AUTO = 2 self._JOG = 3 self._MM = 1 self._IMPERIAL = 0 # paths included to give access to handler files self.SKINPATH = SKINPATH self.CONFIGPATH = CONFIGPATH self.BASEPATH = BASE self.audio_available = False self.use_screen2 = False self.theme_name = "Follow System Theme" self.abs_textcolor = "" self.rel_textcolor = "" self.dtg_textcolor = "" self.err_textcolor = "" self.window_geometry = "" self.window_max = "" self.axis_list = [] self.rotary_joints = False self.active_axis_buttons = [(None,None)] # axis letter,axis number self.abs_color = (0, 65535, 0) self.rel_color = (65535, 0, 0) self.dtg_color = (0, 0, 65535) self.highlight_color = (65535,65535,65535) self.highlight_major = False self.display_order = (_REL,_DTG,_ABS) self.mode_order = (self._MAN,self._MDI,self._AUTO) self.mode_labels = ["Manual Mode","MDI Mode","Auto Mode"] self.IPR_mode = False self.plot_view = ("p","x","y","y2","z","z2") self.task_mode = 0 self.active_gcodes = [] self.active_mcodes = [] for letter in ('x','y','z','a','b','c','u','v','w'): self['%s_abs'%letter] = 0.0 self['%s_rel'%letter] = 0.0 self['%s_dtg'%letter] = 0.0 self['%s_is_homed'%letter] = False self.spindle_request_rpm = 0 self.spindle_dir = 0 self.spindle_speed = 0 self.spindle_start_rpm = 300 self.spindle_preset = 300 self.active_spindle_command = "" # spindle command setting self.active_feed_command = "" # feed command setting self.system = 1 self.estopped = True self.dro_units = self._IMPERIAL self.machine_units = self._IMPERIAL self.tool_in_spindle = 0 self.flood = False self.mist = False self.machine_on = False self.or_limits = False self.op_stop = False self.block_del = False self.all_homed = False self.jog_rate = 15 self.jog_rate_inc = 1 self.jog_rate_max = 60 self.jog_increments = [] self.current_jogincr_index = 0 self.angular_jog_adjustment_flag = False self.angular_jog_increments = [] self.angular_jog_rate = 1800 self.angular_jog_rate_inc = 60 self.angular_jog_rate_max = 7200 self.current_angular_jogincr_index = 0 self.feed_override = 1.0 self.feed_override_inc = .05 self.feed_override_max = 2.0 self.spindle_override = 1.0 self.spindle_override_inc = .05 self.spindle_override_max = 1.2 self.spindle_override_min = .50 self.maxvelocity = 1 self.velocity_override = 1.0 self.velocity_override_inc = .05 self.edit_mode = False self.full_graphics = False self.graphic_move_inc = 20 self.plot_hidden = False self.file = "" self.file_lines = 0 self.line = 0 self.last_line = 0 self.motion_line = 0 self.id = 0 self.dtg = 0.0 self.show_dtg = False self.velocity = 0.0 self.delay = 0.0 self.preppedtool = None self.lathe_mode = False self.diameter_mode = True self.tooleditor = "" self.tooltable = "" self.alert_sound = "/usr/share/sounds/ubuntu/stereo/bell.ogg" self.error_sound = "/usr/share/sounds/ubuntu/stereo/dialog-question.ogg" self.ob = None self.index_tool_dialog = None self.keyboard_dialog = None self.preset_spindle_dialog = None self.spindle_control_dialog = None self.entry_dialog = None self.restart_dialog = None self.key_event_last = None,0 def __getitem__(self, item): return getattr(self, item) def __setitem__(self, item, value): return setattr(self, item, value) # trampoline and load_handlers are used for custom displays class Trampoline(object): def __init__(self,methods): self.methods = methods def __call__(self, *a, **kw): for m in self.methods: m(*a, **kw) def load_handlers(usermod,halcomp,builder,useropts,gscreen): hdl_func = 'get_handlers' mod = object = None def add_handler(method, f): if method in handlers: handlers[method].append(f) else: handlers[method] = [f] handlers = {} for u in usermod: (directory,filename) = os.path.split(u) (basename,extension) = os.path.splitext(filename) if directory == '': directory = '.' if directory not in sys.path: sys.path.insert(0,directory) print _('adding import dir %s' % directory) try: mod = __import__(basename) except ImportError,msg: print ("module '%s' skipped - import error: %s" %(basename,msg)) continue print _("module '%s' imported OK" % mod.__name__) try: # look for functions for temp in ("periodic","connect_signals","initialize_widgets"): h = getattr(mod,temp,None) if h and callable(h): print ("module '%s' : '%s' function found" % (mod.__name__,temp)) # look for 'get_handlers' function h = getattr(mod,hdl_func,None) if h and callable(h): print ("module '%s' : '%s' function found" % (mod.__name__,hdl_func)) objlist = h(halcomp,builder,useropts,gscreen) else: # the module has no get_handlers() callable. # in this case we permit any callable except class Objects in the module to register as handler dbg("module '%s': no '%s' function - registering only functions as callbacks" % (mod.__name__,hdl_func)) objlist = [mod] # extract callback candidates for object in objlist: dbg("Registering handlers in module %s object %s" % (mod.__name__, object)) if isinstance(object, dict): methods = dict.items() else: methods = map(lambda n: (n, getattr(object, n, None)), dir(object)) for method,f in methods: if method.startswith('_'): continue if callable(f): dbg("Register callback '%s' in %s" % (method, basename)) add_handler(method, f) except Exception, e: print ("**** GSCREEN ERROR: trouble looking for handlers in '%s': %s" %(basename, e)) traceback.print_exc() # Wrap lists in Trampoline, unwrap single functions for n,v in list(handlers.items()): if len(v) == 1: handlers[n] = v[0] else: handlers[n] = Trampoline(v) return handlers,mod,object # ok here is the Gscreen class # there are also three other files: # mdi.py for mdi commands (which include non-obvious mdi commands done in maual mode) # preference.py for keeping track of stored user preferences # emc_interface.py which does most of the commands and status of linuxcnc # keep in mind some of the gladeVCP widgets send-commands-to/monitor linuxcnc also class Gscreen: def __init__(self): global xmlname global xmlname2 global gscreen_debug global verbose_debug self.skinname = "gscreen" self.inipath = sys.argv[2] (progdir, progname) = os.path.split(sys.argv[0]) # linuxcnc adds -ini to display name and optparse # can't understand that, so we do it manually for num,temp in enumerate(sys.argv): if temp == '-c': try: print ("**** GSCREEN INFO: Skin name ="),sys.argv[num+1] self.skinname = sys.argv[num+1] except: pass if temp == '-d': gscreen_debug = True if temp == '-v': verbose_debug = True # check for a local translation folder locallocale = os.path.join(CONFIGPATH,"locale") if os.path.exists(locallocale): LOCALEDIR = locallocale domain = self.skinname print ("**** GSCREEN INFO: CUSTOM locale name =",LOCALEDIR,self.skinname) else: locallocale = os.path.join(SKINPATH,"%s/locale"%self.skinname) if os.path.exists(locallocale): LOCALEDIR = locallocale domain = self.skinname print ("**** GSCREEN INFO: SKIN locale name =",LOCALEDIR,self.skinname) else: LOCALEDIR = os.path.join(BASE, "share", "locale") domain = "linuxcnc" locale.setlocale(locale.LC_ALL, '') locale.bindtextdomain(domain, LOCALEDIR) gettext.install(domain, localedir=LOCALEDIR, unicode=True) gettext.bindtextdomain(domain, LOCALEDIR) # main screen localglade = os.path.join(CONFIGPATH,"%s.glade"%self.skinname) if os.path.exists(localglade): print _("\n**** GSCREEN INFO: Using CUSTOM glade file from %s ****"% localglade) xmlname = localglade else: localglade = os.path.join(SKINPATH,"%s/%s.glade"%(self.skinname,self.skinname)) if os.path.exists(localglade): print _("\n**** GSCREEN INFO: Using SKIN glade file from %s ****"% localglade) xmlname = localglade else: print _("\n**** GSCREEN INFO: using STOCK glade file from: %s ****"% xmlname2) try: self.xml = gtk.Builder() self.xml.set_translation_domain(domain) # for locale translations self.xml.add_from_file(xmlname) except: print _("**** Gscreen GLADE ERROR: With main screen xml file: %s"% xmlname) sys.exit(0) # second screen localglade = os.path.join(CONFIGPATH,"%s2.glade"%self.skinname) if os.path.exists(localglade): print _("\n**** GSCREEN INFO: Screen 2 -Using CUSTOM glade file from %s ****"% localglade) xmlname2 = localglade try: self.xml.add_from_file(xmlname2) self.screen2 = True except: print _("**** Gscreen GLADE ERROR: With screen 2's xml file: %s"% xmlname) else: print _("\n**** GSCREEN INFO: No Screen 2 glade file present") self.screen2 = False self.widgets = Widgets(self.xml) self.data = Data() self.keylookup = keybindings.Keylookup() if _AUDIO_AVAILABLE: self.audio = Player() self.data.audio_available = True # access to EMC control self.emc = emc_interface.emc_control(linuxcnc) # access to EMC status self.status = emc_interface.emc_status( self.data, linuxcnc) # access to MDI mdi_labels = mdi_eventboxes = [] self.mdi_control = mdi.mdi_control(gtk, linuxcnc, mdi_labels, mdi_eventboxes) # pull info from the INI file self.inifile = self.emc.emc.ini(self.inipath) # change the display based on the requested axis temp = self.inifile.find("TRAJ","COORDINATES") if temp == None: self.add_alarm_entry("No coordinates entry found in [TRAJ] of INI file") self.data.axis_list = [] for letter in temp: if letter.lower() in self.data.axis_list: continue if not letter.lower() in ["x","y","z","a","b","c","u","v","w"]: continue self.data.axis_list.append(letter.lower()) # check for rotary joints for i in("a","b","c"): if i in self.data.axis_list: self.data.rotary_joints = True break # 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") if units==None: self.add_alarm_entry(_("No UNITS entry found in [TRAJ] or [AXIS_0] of INI file")) if units=="mm" or units=="metric" or units == "1.0": self.machine_units_mm=1 conversion=[1.0/25.4]*3+[1]*3+[1.0/25.4]*3 else: self.machine_units_mm=0 conversion=[25.4]*3+[1]*3+[25.4]*3 self.status.set_machine_units(self.machine_units_mm,conversion) # set-up HAL component try: self.halcomp = hal.component("gscreen") except: print _("*** Gscreen ERROR: Asking for a HAL component using a name that already exists.") sys.exit(0) panel = gladevcp.makepins.GladePanel( self.halcomp, xmlname, self.xml, None) # at this point, any glade HAL widgets and their pins are set up. # look for custom handler files: HANDLER_FN = "%s_handler.py"%self.skinname local_handler_path = os.path.join(CONFIGPATH,HANDLER_FN) skin_handler_path = os.path.join(SKINPATH,"%s/%s"%(self.skinname,HANDLER_FN)) if os.path.exists(local_handler_path): temp = [local_handler_path] elif os.path.exists(skin_handler_path): temp = [skin_handler_path] else: temp = [] dbg("**** GSCREEN INFO: handler file path: %s"%temp) handlers,self.handler_module,self.handler_instance = load_handlers(temp,self.halcomp,self.xml,[],self) self.xml.connect_signals(handlers) # Look for an optional preferece file path otherwise it uses ~/.gscreen_preferences # then initiate access to saved prefernces temp = self.inifile.find("DISPLAY","PREFERENCE_FILE_PATH") dbg("**** GSCREEN INFO: Preference file path: %s"%temp) self.prefs = preferences.preferences(temp) # Intialize prefereces either from the handler file or from Gscreen if "initialize_preferences" in dir(self.handler_instance): self.handler_instance.initialize_preferences() else: self.initialize_preferences() # check for ladder loaded self.data.is_ladder = hal.component_exists('classicladder_rt') # get the system wide theme settings = gtk.settings_get_default() settings.props.gtk_button_images = True self.data.system_theme = settings.get_property("gtk-theme-name") # jogging increments increments = self.inifile.find("DISPLAY", "INCREMENTS") if increments: if not "continuous" in increments: increments +=",continuous" if "," in increments: self.data.jog_increments = [i.strip() for i in increments.split(",")] else: self.data.jog_increments = increments.split() else: if self.machine_units_mm ==self.data._MM: self.data.jog_increments = [".001 mm",".01 mm",".1 mm","1 mm","continuous"] else: self.data.jog_increments = [".0001 in",".001 in",".01 in",".1 in","continuous"] self.add_alarm_entry(_("No default jog increments entry found in [DISPLAY] of INI file")) # angular jogging increments increments = self.inifile.find("DISPLAY", "ANGULAR_INCREMENTS") if increments: if not "continuous" in increments: increments +=",continuous" if "," in increments: self.data.angular_jog_increments = [i.strip() for i in increments.split(",")] else: self.data.angular_jog_increments = increments.split() else: self.data.angular_jog_increments = ["1","45","180","360","continuous"] self.add_alarm_entry(_("No default angular jog increments entry found in [DISPLAY] of INI file")) # set default jog rate # must convert from INI's units per second to gscreen's units per minute temp = self.inifile.find("DISPLAY","DEFAULT_LINEAR_VELOCITY") if temp: temp = float(temp)*60 else: temp = self.data.jog_rate self.add_alarm_entry(_("No DEFAULT_LINEAR_VELOCITY entry found in [DISPLAY] of INI file: using internal default of %s"%temp)) self.data.jog_rate = float(temp) self.emc.continuous_jog_velocity(float(temp),None) # set max jog rate # must convert from INI's units per second to gscreen's units per minute temp = self.inifile.find("DISPLAY","MAX_LINEAR_VELOCITY") if temp: temp = float(temp)*60 else: temp = self.data.jog_rate_max self.add_alarm_entry(_("No MAX_LINEAR_VELOCITY entry found in [DISPLAY] of INI file: using internal default of %s"%temp)) self.data.jog_rate_max = float(temp) # max velocity settings: more then one place to check # This is the maximum velocity of the machine temp = self.inifile.find("TRAJ","MAX_VELOCITY") if temp == None: self.add_alarm_entry(_("No MAX_VELOCITY found in [TRAJ] of the INI file")) temp = 1.0 self.data._maxvelocity = float(temp) # look for angular defaults if there is angular axis if "a" in self.data.axis_list or "b" in self.data.axis_list or "c" in self.data.axis_list: # set default angular jog rate # must convert from INI's units per second to gscreen's units per minute temp = self.inifile.find("DISPLAY","DEFAULT_ANGULAR_VELOCITY") if temp: temp = float(temp)*60 else: temp = self.data.angular_jog_rate self.add_alarm_entry(_("No DEFAULT_ANGULAR_VELOCITY entry found in [DISPLAY] of INI file: using internal default of %s"%temp)) self.data.angular_jog_rate = float(temp) self.emc.continuous_jog_velocity(None,float(temp)) # set default angular jog rate # must convert from INI's units per second to gscreen's units per minute temp = self.inifile.find("DISPLAY","MAX_ANGULAR_VELOCITY") if temp: temp = float(temp)*60 else: temp = self.data.angular_jog_rate_max self.add_alarm_entry(_("No MAX_ANGULAR_VELOCITY entry found in [DISPLAY] of INI file: using internal default of %s"%temp)) self.data.angular_jog_rate_max = float(temp) # check for override settings temp = self.inifile.find("DISPLAY","MAX_SPINDLE_OVERRIDE") if temp: self.data.spindle_override_max = float(temp) else: self.add_alarm_entry(_("No MAX_SPINDLE_OVERRIDE entry found in [DISPLAY] of INI file")) temp = self.inifile.find("DISPLAY","MIN_SPINDLE_OVERRIDE") if temp: self.data.spindle_override_min = float(temp) else: self.add_alarm_entry(_("No MIN_SPINDLE_OVERRIDE entry found in [DISPLAY] of INI file")) temp = self.inifile.find("DISPLAY","MAX_FEED_OVERRIDE") if temp: self.data.feed_override_max = float(temp) else: self.add_alarm_entry(_("No MAX_FEED_OVERRIDE entry found in [DISPLAY] of INI file")) # if it's a lathe config, set the tooleditor style self.data.lathe_mode = bool(self.inifile.find("DISPLAY", "LATHE")) if self.data.lathe_mode: self.add_alarm_entry(_("This screen will be orientated for Lathe options")) # get the path to the tool table self.data.tooltable = self.inifile.find("EMCIO","TOOL_TABLE") # see if the user specified a tool editor self.data.tooleditor = self.inifile.find("DISPLAY","TOOL_EDITOR") # see if the user specified a tool editor self.data.varfile = self.inifile.find("RS274NGC","PARAMETER_FILE") if "initialize_keybindings" in dir(self.handler_instance): self.handler_instance.initialize_keybindings() else: self.initialize_keybindings() # TODO the user should be able to invoke this so they know what methods are available # and what handers are registered #print handlers if "initialize_pins" in dir(self.handler_instance): self.handler_instance.initialize_pins() else: self.initialize_pins() if "initialize_manual_toolchange" in dir(self.handler_instance): self.handler_instance.initialize_manual_toolchange() else: self.initialize_manual_toolchange() if "connect_signals" in dir(self.handler_instance): self.handler_instance.connect_signals(handlers) else: self.connect_signals(handlers) # Set up the widgets if "initialize_widgets" in dir(self.handler_instance): self.handler_instance.initialize_widgets() else: self.initialize_widgets() # see if there are user messages in the ini file self.message_setup() # ok everything that might make HAL pins should be done now - let HAL know that self.halcomp.ready() try: self.widgets._terminal.feed_child('halcmd show pin gscreen\n') except: pass # timers for display updates temp = self.inifile.find("DISPLAY","CYCLE_TIME") if not temp: self.add_alarm_entry(_("CYCLE_TIME in [DISPLAY] of INI file is missing: defaulting to 100ms")) temp = 100 elif float(temp) < 50: self.add_alarm_entry(_("CYCLE_TIME in [DISPLAY] of INI file is too small: defaulting to 100ms")) temp = 100 print _("timeout %d" % int(temp)) if "timer_interrupt" in dir(self.handler_instance): gobject.timeout_add(int(temp), self.handler_instance.timer_interrupt) else: gobject.timeout_add(int(temp), self.timer_interrupt) def initialize_keybindings(self): self.widgets.window1.connect('key_press_event', self.on_key_event,1) self.widgets.window1.connect('key_release_event', self.on_key_event,0) def initialize_preferences(self): self.init_dro_pref() self.init_theme_pref() self.init_window_geometry_pref() self.init_keybinding_pref() self.init_general_pref() def init_dro_pref(self): self.data.abs_textcolor = self.prefs.getpref('abs_textcolor', '#0000FFFF0000', str) self.data.dtg_textcolor = self.prefs.getpref('dtg_textcolor', '#00000000FFFF', str) self.data.rel_textcolor = self.prefs.getpref('rel_textcolor', '#FFFF00000000', str) self.data.show_dtg = self.prefs.getpref('show_dtg', False, bool) def init_theme_pref(self): self.data.theme_name = self.prefs.getpref('gtk_theme', 'Redmond', str) def init_window_geometry_pref(self): self.data.fullscreen1 = self.prefs.getpref('fullscreen1', False, bool) self.data.use_screen2 = self.prefs.getpref('use_screen2', False, bool) self.data.window_geometry = self.prefs.getpref('window_geometry', 'default', str) self.data.window_max = self.prefs.getpref('window_force_max', False, bool) self.data.window2_geometry = self.prefs.getpref('window2_geometry', 'default', str) self.data.window2_max = self.prefs.getpref('window2_force_max', False, bool) def init_keybinding_pref(self): self.keylookup.add_binding('Right', self.prefs.getpref('Key_Right', 'XPOS', str,"KEYCODES")) self.keylookup.add_binding('Left', self.prefs.getpref('Key_Left', 'XNEG', str,"KEYCODES")) self.keylookup.add_binding('Up', self.prefs.getpref('Key_Up', 'YPOS', str,"KEYCODES")) self.keylookup.add_binding('Down', self.prefs.getpref('Key_Down', 'YNEG', str,"KEYCODES")) self.keylookup.add_binding('Page_Up', self.prefs.getpref('Key_Page_Up', 'ZPOS', str,"KEYCODES")) self.keylookup.add_binding('Page_Down', self.prefs.getpref('Key_Page_Down', 'ZNEG', str,"KEYCODES")) self.keylookup.add_binding('bracketleft', self.prefs.getpref('Key_bracketleft', 'APOS', str,"KEYCODES")) self.keylookup.add_binding('bracketright', self.prefs.getpref('Key_bracketright', 'ANEG', str,"KEYCODES")) self.keylookup.add_binding('i', self.prefs.getpref('Key_i', 'INCREMENTS', str,"KEYCODES")) self.keylookup.add_binding('I', self.prefs.getpref('Key_I', 'INCREMENTS', str,"KEYCODES")) self.keylookup.add_binding('F1', self.prefs.getpref('Key_F1', 'ESTOP', str,"KEYCODES")) self.keylookup.add_binding('F2', self.prefs.getpref('Key_F2', 'POWER', str,"KEYCODES")) self.keylookup.add_binding('Escape', self.prefs.getpref('Key_Escape', 'ABORT', str,"KEYCODES")) def init_general_pref(self): self.data.alert_sound = self.prefs.getpref('audio_alert', self.data.alert_sound, str) self.data.desktop_notify = self.prefs.getpref('desktop_notify', True, bool) self.data.diameter_mode = self.prefs.getpref('diameter_mode', False, bool) self.data.display_order = self.prefs.getpref('display_order', (0,1,2), repr) self.data.dro_units = self.prefs.getpref('dro_is_metric', False, bool) if self.data.dro_units: # set linuxcnc as well self.status.dro_mm(0) else: self.status.dro_inch(0) self.data.error_sound = self.prefs.getpref('audio_error', self.data.error_sound, str) self.data.error_font_name = self.prefs.getpref('error_font', 'Sans Bold 10', str) self.data.err_textcolor = self.prefs.getpref('err_textcolor', 'default', str) self.data.grid_size = self.prefs.getpref('grid_size', 1.0 , float) self.data.hide_cursor = self.prefs.getpref('hide_cursor', False, bool) self.data.plot_view = self.prefs.getpref('view', ("p","x","y","y2","z","z2"), repr) self.data.show_offsets = self.prefs.getpref('show_offsets', True, bool) self.data.spindle_start_rpm = self.prefs.getpref('spindle_start_rpm', 300 , float) self.data.unlock_code = self.prefs.getpref('unlock_code', '123', str) self.data.embedded_keyboard = self.prefs.getpref('embedded_keyboard', True, bool) if self.prefs.getpref('dro_actual', False, bool): self.status.dro_actual(0) else: self.status.dro_commanded(0) # toolsetting reference type if self.prefs.getpref('toolsetting_fixture', False, bool): self.g10l11 = 1 else: self.g10l11 = 0 # initialize default widgets def initialize_widgets(self): self.init_show_windows() self.init_dynamic_tabs() self.init_axis_frames() self.init_dro_colors() self.init_screen2() self.init_fullscreen1() self.init_gremlin() self.init_manual_spindle_controls() self.init_dro() self.init_audio() self.init_desktop_notify() self.init_statusbar() self.init_entry() self.init_tooleditor() self.init_offsetpage() self.init_embeded_terminal() self.init_themes() self.init_screen1_geometry() self.init_running_options() self.init_mode() self.init_sensitive_on_off() self.init_sensitive_run_idle() self.init_sensitive_all_homed() self.init_sensitive_edit_mode() self.init_sensitive_override_mode() self.init_sensitive_graphics_mode() self.init_sensitive_origin_mode() self.init_hide_cursor() self.init_state() def show_try_errors(self): global verbose_debug if verbose_debug: exc_type, exc_value, exc_traceback = sys.exc_info() formatted_lines = traceback.format_exc().splitlines() print print "****Gscreen verbose debugging:",formatted_lines[0] traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) print formatted_lines[-1] def verbosely_print(self,data): global verbose_debug if verbose_debug: print data def init_axis_frames(self): for letter in ('x','y','z','a','b','c','u','v','w'): try: frame_for_letter = eval("self.widgets." + 'frame_' + letter) except: self.show_try_errors() continue if letter in self.data.axis_list: frame_for_letter.show() # don't show image6 when axes other than xyz are present if letter in ('a','b','c','u','v','w'): self.widgets.image6.hide() ;# make more room for axis display else: # hide unneeded frames for axes not in use frame_for_letter.hide() ;# frame not relevant if self.data.rotary_joints: try: self.widgets.button_select_rotary_adjust.show() self.widgets.angular_jog_increments.show() self.widgets.angular_jog_rate.show() except: self.show_try_errors() def init_dynamic_tabs(self): # dynamic tabs setup self._dynamic_childs = {} atexit.register(self.kill_dynamic_childs) self.set_dynamic_tabs() def init_dro_colors(self): self.widgets.abs_colorbutton.set_color(gtk.gdk.color_parse(self.data.abs_textcolor)) self.set_abs_color() self.widgets.rel_colorbutton.set_color(gtk.gdk.color_parse(self.data.rel_textcolor)) self.set_rel_color() self.widgets.dtg_colorbutton.set_color(gtk.gdk.color_parse(self.data.dtg_textcolor)) self.set_dtg_color() def init_screen2(self): self.widgets.use_screen2.set_active(self.data.use_screen2) def init_fullscreen1(self): self.widgets.fullscreen1.set_active(self.data.fullscreen1) def init_gremlin(self): self.widgets.show_offsets.set_active( self.data.show_offsets ) self.widgets.gremlin.show_offsets = self.data.show_offsets self.widgets.grid_size.set_value(self.data.grid_size) self.widgets.gremlin.grid_size = self.data.grid_size self.widgets.gremlin.set_property('view',self.data.plot_view[0]) self.widgets.gremlin.set_property('metric_units',(self.data.dro_units == self.data._MM)) def init_manual_spindle_controls(self): self.widgets.spindle_start_rpm.set_value(self.data.spindle_start_rpm) self.block("s_display_fwd") self.widgets.s_display_fwd.set_active(True) self.unblock("s_display_fwd") self.preset_spindle_speed(self.data.spindle_start_rpm) def init_dro(self): self.widgets.diameter_mode.set_active(self.data.diameter_mode) self.widgets.dro_units.set_active(self.data.dro_units) def init_audio(self): self.widgets.audio_alert_chooser.set_filename(self.data.alert_sound) self.widgets.audio_error_chooser.set_filename(self.data.error_sound) def init_desktop_notify(self): self.widgets.desktop_notify.set_active(self.data.desktop_notify) def init_statusbar(self): self.statusbar_id = self.widgets.statusbar1.get_context_id("Statusbar1") self.homed_status_message = self.widgets.statusbar1.push(1,"Ready For Homing") def init_entry(self): return # first we hide all the axis columns the unhide the ones we want # if it's a lathe config we show lathe related columns # and we load the tooltable data def init_tooleditor(self): self.widgets.tooledit1.set_visible("abcxyzuvwijq",False) for axis in self.data.axis_list: self.widgets.tooledit1.set_visible("%s"%axis,True) if self.data.lathe_mode: self.widgets.tooledit1.set_visible("ijq",True) path = os.path.join(CONFIGPATH,self.data.tooltable) self.widgets.tooledit1.set_filename(path) # Only show the rows of the axes we use # set the var path so offsetpage can fill in all the user system offsets def init_offsetpage(self): self.widgets.offsetpage1.set_col_visible('xyzabcuvw',False) temp ="" for axis in self.data.axis_list: temp=temp+axis self.widgets.offsetpage1.set_col_visible(temp,True) path = os.path.join(CONFIGPATH,self.data.varfile) self.widgets.offsetpage1.set_filename(path) def init_embeded_terminal(self): # add terminal window self.widgets._terminal = vte.Terminal () self.widgets._terminal.connect ("child-exited", lambda term: gtk.main_quit()) self.widgets._terminal.fork_command() self.widgets._terminal.show() window = self.widgets.terminal_window.add(self.widgets._terminal) self.widgets.terminal_window.connect('delete-event', lambda window, event: gtk.main_quit()) self.widgets.terminal_window.show() def init_themes(self): # If there are themes then add them to combo box if os.path.exists(themedir): model = self.widgets.theme_choice.get_model() model.clear() model.append(("Follow System Theme",)) temp = 0 names = os.listdir(themedir) names.sort() for search,dirs in enumerate(names): model.append((dirs,)) if dirs == self.data.theme_name: temp = search+1 self.widgets.theme_choice.set_active(temp) settings = gtk.settings_get_default() if not self.data.theme_name == "Follow System Theme": settings.set_string_property("gtk-theme-name", self.data.theme_name, "") def init_screen1_geometry(self): # maximize window or set geometry and optionally maximize if "max" in self.data.window_geometry: self.widgets.window1.maximize() elif self.data.window_geometry == "default": self.show_try_errors() else: good = self.widgets.window1.parse_geometry(self.data.window_geometry) if self.data.window_max: self.widgets.window1.maximize() if not good: print _("**** WARNING GSCREEN: could not understand the window geometry info in hidden preference file") if self.widgets.fullscreen1.get_active(): self.widgets.window1.fullscreen() def init_running_options(self): self.widgets.button_block_delete.set_active(self.prefs.getpref('blockdel', False)) self.emc.blockdel(self.data.block_del) self.widgets.button_option_stop.set_active(self.prefs.getpref('opstop', False)) self.emc.opstop(self.data.op_stop) def init_hide_cursor(self): self.widgets.hide_cursor.set_active(self.data.hide_cursor) # hide cursor if requested # that also sets the graphics to use touchscreen controls if self.data.hide_cursor: self.widgets.window1.window.set_cursor(INVISABLE) self.widgets.gremlin.set_property('use_default_controls',False) else: self.widgets.window1.window.set_cursor(None) self.widgets.gremlin.set_property('use_default_controls',True) def init_mode(self): label = self.data.mode_labels self.widgets.button_mode.set_label(label[self.data.mode_order[0]]) # set to 'manual mode' self.mode_changed(self.data.mode_order[0]) # buttons that need to be sensitive based on the machine being on or off def init_sensitive_on_off(self): self.data.sensitive_on_off = ["vmode0","mode0","mode1","button_homing","button_override","button_graphics","frame_s","button_mode","button_restart"] for axis in self.data.axis_list: self.data.sensitive_on_off.append("axis_%s"% axis) # buttons that need to be sensitive based on the interpeter runing or being idle def init_sensitive_run_idle(self): self.data.sensitive_run_idle = ["button_edit","button_load","button_mode","button_restart"] for axis in self.data.axis_list: self.data.sensitive_run_idle.append("axis_%s"% axis) def init_sensitive_all_homed(self): self.data.sensitive_all_homed = ["button_zero_origin","button_offset_origin","button_select_system","button_tool_set"] def init_sensitive_edit_mode(self): self.data.sensitive_edit_mode = ["button_mode","button_menu","button_graphics","button_override","button_restart","button_single_step","button_run", "ignore_limits"] def init_sensitive_override_mode(self): self.data.sensitive_override_mode = ["spindle_preset","spindle_control","spindle_increase","spindle_decrease","s_display_fwd", "s_display_rev","button_graphics","button_homing","button_mode","button_jog_mode","button_flood_coolant", "button_mist_coolant","button_tool_editor","button_tool_set"] for axis in self.data.axis_list: self.data.sensitive_override_mode.append("axis_%s"% axis) def init_sensitive_graphics_mode(self): self.data.sensitive_graphics_mode = ["button_override","button_homing","button_mode", "button_zero_origin","button_offset_origin","button_plus","button_minus","vmode0","button_tool_set"] for axis in self.data.axis_list: self.data.sensitive_graphics_mode.append("axis_%s"% axis) def init_sensitive_origin_mode(self): self.data.sensitive_origin_mode = ["button_override","button_graphics","button_homing","button_mode", "button_zero_origin","button_offset_origin","button_jog_mode","button_flood_coolant","button_mist_coolant","button_tool_editor","button_tool_set"] for axis in self.data.axis_list: self.data.sensitive_origin_mode.append("axis_%s"% axis) # this needs to be last as it causes methods to be called (eg to sensitize buttons) def init_state(self): for num,i in enumerate(self.data.jog_increments): if i == "continuous": break self.data.current_jogincr_index = num try: jogincr = self.data.jog_increments[self.data.current_jogincr_index] self.widgets.jog_increments.set_text(jogincr) except: self.show_try_errors() try: for num,i in enumerate(self.data.angular_jog_increments): if i == "continuous": break self.data.current_angular_jogincr_index = num jogincr = self.data.angular_jog_increments[self.data.current_angular_jogincr_index] self.widgets.angular_jog_increments.set_text(jogincr) except: self.show_try_errors() self.on_hal_status_state_off(None) try: self.widgets.search_box.hide() except: self.show_try_errors() self.add_alarm_entry(_("Control powered up and initialized")) def init_show_windows(self): # set title and display everything including the second screen if requested if self.skinname == "gscreen": title = "Gscreen" else: title = "Gscreen-%s"% self.skinname self.widgets.window1.set_title("%s for linuxcnc"% title) if self.screen2: self.widgets.window2.show() self.widgets.window2.move(0,0) if not self.data.use_screen2: self.widgets.window2.hide() self.widgets.window1.show() def init_unlock_code(self): print "unlock code #",int(self.data.unlock_code) self.widgets.unlock_number.set_value(int(self.data.unlock_code)) # general call to initialize HAL pins # select this if you want all the default pins or select each call for # which ones you want def initialize_pins(self): self.init_spindle_pins() self.init_coolant_pins() self.init_jog_pins() self.init_override_pins() self.init_control_pins() def init_spindle_pins(self): self.halcomp.newpin("spindle-readout-in", hal.HAL_FLOAT, hal.HAL_IN) def init_coolant_pins(self): self.halcomp.newpin("aux-coolant-m7-out", hal.HAL_BIT, hal.HAL_OUT) self.halcomp.newpin("aux-coolant-m8-out", hal.HAL_BIT, hal.HAL_OUT) self.halcomp.newpin("mist-coolant-out", hal.HAL_BIT, hal.HAL_OUT) self.halcomp.newpin("flood-coolant-out", hal.HAL_BIT, hal.HAL_OUT) def init_jog_pins(self): for axis in self.data.axis_list: self.halcomp.newpin("jog-enable-%s-out"% (axis), hal.HAL_BIT, hal.HAL_OUT) self.halcomp.newpin("jog-enable-out", hal.HAL_BIT, hal.HAL_OUT) self.halcomp.newpin("jog-increment-out", hal.HAL_FLOAT, hal.HAL_OUT) #self.data['jog-increment-in'] = hal_glib.GPin(self.halcomp.newpin('jog-increment-in', hal.HAL_S32, hal.HAL_IN)) #self.data['jog-increment-in'].connect('value-changed', self.on_hal_jog_increments_changed) #self.data['jog-rate-in'] = hal_glib.GPin(self.halcomp.newpin('jog-rate-in', hal.HAL_S32, hal.HAL_IN)) #self.data['jog-rate-in'].connect('value-changed', self.on_hal_jog_rate_changed) # pins used for selecting an encoder to adjust overrides def init_override_pins(self): self.halcomp.newpin("s-override-enable-out", hal.HAL_BIT, hal.HAL_OUT) self.halcomp.newpin("f-override-enable-out", hal.HAL_BIT, hal.HAL_OUT) self.halcomp.newpin("mv-override-enable-out", hal.HAL_BIT, hal.HAL_OUT) def init_control_pins(self): self.data['cycle_start'] = hal_glib.GPin(self.halcomp.newpin('cycle-start', hal.HAL_BIT, hal.HAL_IN)) self.data['cycle_start'].connect('value-changed', self.on_cycle_start_changed) self.data['abort'] = hal_glib.GPin(self.halcomp.newpin('abort', hal.HAL_BIT, hal.HAL_IN)) self.data['abort'].connect('value-changed', self.on_abort_changed) self.data['feed_hold'] = hal_glib.GPin(self.halcomp.newpin('feed-hold', hal.HAL_BIT, hal.HAL_IN)) self.data['feed_hold'].connect('value-changed', self.on_feed_hold_changed) def initialize_manual_toolchange(self): # for manual tool change dialog self.halcomp.newpin("tool-number", hal.HAL_S32, hal.HAL_IN) self.halcomp.newpin("tool-changed", hal.HAL_BIT, hal.HAL_OUT) self.data['change-tool'] = hal_glib.GPin(self.halcomp.newpin('change-tool', hal.HAL_BIT, hal.HAL_IN)) # you can override manual tool change if "on_tool_change" in dir(self.handler_instance): self.data['change-tool'].connect('value-changed', self.handler_instance.on_tool_change) else: self.data['change-tool'].connect('value-changed', self.on_tool_change) # *** GLADE callbacks **** def on_keycall_ABORT(self,state,SHIFT,CNTRL,ALT): if state: # only activate when pushed not when released self.widgets.hal_action_stop.emit("activate") return True def on_keycall_ESTOP(self,state,SHIFT,CNTRL,ALT): if state: self.widgets.button_estop.emit('clicked') return True def on_keycall_POWER(self,state,SHIFT,CNTRL,ALT): if state: self.widgets.button_machine_on.emit('clicked') return True def on_keycall_XPOS(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_X,1,state) return True def on_keycall_XNEG(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_X,0,state) return True def on_keycall_YPOS(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_Y,1,state) return True def on_keycall_YNEG(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_Y,0,state) return True def on_keycall_ZPOS(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_Z,1,state) return True def on_keycall_ZNEG(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_Z,0,state) return True def on_keycall_APOS(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_A,1,state) return True def on_keycall_ANEG(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required self.do_key_jog(_A,0,state) return True def on_keycall_INCREMENTS(self,state,SHIFT,CNTRL,ALT): if state and self.data._MAN in self.check_mode(): # manual mode required if SHIFT: self.set_jog_increments(index_dir = -1) else: self.set_jog_increments(index_dir = 1) return True def on_keycall_(self,state,SHIFT,CNTRL,ALT): if self.data._MAN in self.check_mode(): # manual mode required pass return True def on_button_spindle_controls_clicked(self,widget): self.spindle_dialog() def on_button_select_rotary_adjust_clicked(self,widget): self.data.angular_jog_adjustment_flag = widget.get_active() print self.data.angular_jog_adjustment_flag def search_fwd(self,widget): self.widgets.gcode_view.text_search(direction=True,text=self.widgets.search_entry.get_text()) def search_bwd(self,widget): self.widgets.gcode_view.text_search(direction=False,text=self.widgets.search_entry.get_text()) def undo_edit(self,widget): self.widgets.gcode_view.undo() def redo_edit(self,widget): self.widgets.gcode_view.redo() def keypress(self,accelgroup, acceleratable, accel_key, accel_mods): print gtk.accelerator_name(accel_key,accel_mods),acceleratable,accel_mods, return True def on_key_event(self,widget, event,state): CNTRL = SHIFT = ALT = 0 keyname = gtk.gdk.keyval_name(event.keyval) self.verbosely_print("Key %s (%d) was pressed state: %d last: %s" % (keyname, event.keyval,state, self.data.key_event_last)) if event.state & gtk.gdk.CONTROL_MASK: CNTRL = 1 self.verbosely_print("Control was being held down") if event.state & gtk.gdk.MOD1_MASK: ALT = 1 self.verbosely_print("Alt was being held down") if event.state & gtk.gdk.SHIFT_MASK: SHIFT = 1 self.verbosely_print("Shift was being held down") if keyname in( "Shift_L","Shift_R"): return True # ignore shift key press if self.data.key_event_last[0] == keyname and self.data.key_event_last[1] == state : return True self.data.key_event_last = keyname,state try: method = self.keylookup.convert(keyname) if method: try: return self.handler_instance[method](state,SHIFT,CNTRL,ALT) except: self.show_try_errors() return self[method](state,SHIFT,CNTRL,ALT) except: self.show_try_errors() def on_cycle_start_changed(self,hal_object): print "cycle start change" h = self.halcomp if not h["cycle-start"]: return if self.data.mode_order[0] == self.data._AUTO: self.add_alarm_entry(_("Cycle start pressed in AUTO mode")) self.widgets.hal_toggleaction_run.emit('activate') elif self.data.mode_order[0] == self.data._MDI: self.add_alarm_entry(_("Cycle start pressed in MDI mode")) self.widgets.hal_mdihistory.submit() def on_abort_changed(self,hal_object): print "abort change" h = self.halcomp if not h["abort"]: return self.widgets.hal_action_stop.emit("activate") def on_feed_hold_changed(self,hal_object): print "feed-hold change" h = self.halcomp self.widgets.hal_toggleaction_pause.set_active(h["feed-hold"]) # Here we create a manual tool change dialog # This can be overridden in a handler file def on_tool_change(self,widget): h = self.halcomp c = h['change-tool'] n = h['tool-number'] cd = h['tool-changed'] print "tool change",c,cd,n if c: message = _("Please change to tool # %s, then click OK."% n) self.data.tool_message = self.notify(_("INFO:"),message,None) self.warning_dialog(message, True,pinname="TOOLCHANGE") else: h['tool-changed'] = False def on_spindle_speed_adjust(self,widget): # spindle increase /decrease controls if self.mdi_control.mdi_is_reading(): self.notify(_("INFO:"),_("Can't start spindle manually while MDI busy"),INFO_ICON) return elif self.data.mode_order[0] == self.data._AUTO: self.notify(_("INFO:"),_("can't start spindle manually in Auto mode"),INFO_ICON) return if widget == self.widgets.spindle_increase: self.spindle_adjustment(True,True) elif widget == self.widgets.spindle_decrease: self.spindle_adjustment(False,True) # start the spindle according to preset rpm and direction buttons, unless interp is busy def on_spindle_control_clicked(self,*args): if self.mdi_control.mdi_is_reading(): self.notify(_("INFO:"),_("Can't start spindle manually while MDI busy"),INFO_ICON) return elif self.data.mode_order[0] == self.data._AUTO: self.notify(_("INFO:"),_("can't start spindle manually in Auto mode"),INFO_ICON) return if not self.data.spindle_speed == 0: self.emc.spindle_off(1) return if not self.widgets.s_display_fwd.get_active() and not self.widgets.s_display_rev.get_active(): self.notify(_("INFO:"),_("No direction selected for spindle"),INFO_ICON) return if self.widgets.s_display_fwd.get_active(): self.adjust_spindle_rpm(self.data.spindle_preset,1) else: self.adjust_spindle_rpm(self.data.spindle_preset,-1) # dialog for setting the spindle preset speed def on_preset_spindle(self,*args): if self.data.preset_spindle_dialog: return label = gtk.Label(_("Spindle Speed Preset Entry")) label.modify_font(pango.FontDescription("sans 20")) self.data.preset_spindle_dialog = gtk.Dialog(_("Spindle Speed Preset Entry"), self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) calc = gladevcp.Calculator() self.data.preset_spindle_dialog.vbox.pack_start(label) self.data.preset_spindle_dialog.vbox.add(calc) calc.set_value("") calc.set_property("font","sans 20") calc.set_editable(True) calc.entry.connect("activate", lambda w : self.data.preset_spindle_dialog.emit('response',gtk.RESPONSE_ACCEPT)) self.data.preset_spindle_dialog.parse_geometry("400x400") self.data.preset_spindle_dialog.set_decorated(False) self.data.preset_spindle_dialog.show_all() self.data.preset_spindle_dialog.connect("response", self.on_preset_spindle_return,calc) def on_preset_spindle_return(self,widget,result,calc): if result == gtk.RESPONSE_ACCEPT: data = calc.get_value() if data == None: return self.preset_spindle_speed(data) widget.destroy() self.data.preset_spindle_dialog = None # dialog for manually calling a tool def on_index_tool(self,*args): if self.data.index_tool_dialog: return self.data.index_tool_dialog = gtk.Dialog(_("Manual Tool Index Entry"), self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) label = gtk.Label(_("Manual Tool Index Entry")) label.modify_font(pango.FontDescription("sans 20")) self.data.index_tool_dialog.vbox.pack_start(label) calc = gladevcp.Calculator() self.data.index_tool_dialog.vbox.add(calc) calc.set_value("") calc.set_property("font","sans 20") calc.set_editable(True) calc.entry.connect("activate", lambda w : self.data.index_tool_dialog.emit('response',gtk.RESPONSE_ACCEPT)) self.data.index_tool_dialog.parse_geometry("400x400") self.data.index_tool_dialog.show_all() calc.num_pad_only(True) calc.integer_entry_only(True) self.data.index_tool_dialog.connect("response", self.on_index_tool_return,calc) def on_index_tool_return(self,widget,result,calc): if result == gtk.RESPONSE_ACCEPT: raw = calc.get_value() try: tool = abs(int((raw))) self.mdi_control.index_tool(tool) except: return widget.destroy() self.data.index_tool_dialog = None def set_grid_size(self,widget): data = widget.get_value() self.widgets.gremlin.set_property('grid_size',data) self.prefs.putpref('grid_size', data,float) # from prefererence page def set_spindle_start_rpm(self,widget): data = widget.get_value() self.data.spindle_start_rpm = data self.prefs.putpref('spindle_start_rpm', data,float) self.preset_spindle_speed(data) def update_preview(self,widget): file = widget.get_filename() if file: try: test = Player() test.set_sound(file) test.run() except:pass def change_sound(self,widget,sound): file = widget.get_filename() if file: self.data[sound+"_sound"] = file temp = "audio_"+ sound self.prefs.putpref(temp, file, str) # manual spindle control def on_s_display_fwd_toggled(self,widget): if widget.get_active(): if self.widgets.s_display_fwd.get_active(): self.emc.spindle_off(1) self.block("s_display_rev") self.widgets.s_display_rev.set_active(False) self.unblock("s_display_rev") else: self.block("s_display_fwd") widget.set_active(True) self.unblock("s_display_fwd") # manual spindle control def on_s_display_rev_toggled(self,widget): if widget.get_active(): if self.widgets.s_display_fwd.get_active(): self.emc.spindle_off(1) self.block("s_display_fwd") self.widgets.s_display_fwd.set_active(False) self.unblock("s_display_fwd") else: self.block("s_display_rev") widget.set_active(True) self.unblock("s_display_rev") # for plot view controls with touchscreen def on_eventbox_gremlin_enter_notify_event(self,widget,event): if self.widgets.button_graphics.get_active(): if self.widgets.button_zoom.get_active(): self.widgets.gremlin.start_continuous_zoom(event.y) elif self.widgets.button_rotate_v.get_active(): self.widgets.gremlin.select_prime(event.x,event.y) self.widgets.gremlin.set_mouse_start(event.x,event.y) # for plot view controls with touchscreen def on_eventbox_gremlin_leave_notify_event(self,widget,event): self.widgets.gremlin.select_fire(event.x,event.y) # for plot view controls with touchscreen or mouse # if using mouse and when in graphics adjustment mode, # we don't use mouse controls when we have selected button controls def on_gremlin_motion(self,widget,event): if self.widgets.button_graphics.get_active(): self.widgets.gremlin.set_property('use_default_controls',False) if self.data.hide_cursor: if self.widgets.button_zoom.get_active(): self.widgets.gremlin.continuous_zoom(event.y) elif self.widgets.button_pan_v.get_active(): self.pan(event.x,event.y) elif self.widgets.button_pan_h.get_active(): self.pan(event.x,event.y) elif self.widgets.button_rotate_v.get_active(): self.rotate(event.x,event.y) elif self.widgets.button_rotate_h.get_active(): self.rotate(event.x,event.y) elif self.widgets.button_zoom.get_active() or self.widgets.button_pan_v.get_active(): return elif self.widgets.button_pan_h.get_active() or self.widgets.button_rotate_v.get_active(): return elif self.widgets.button_rotate_h.get_active(): return else: self.widgets.gremlin.set_property('use_default_controls',True) else: self.widgets.gremlin.set_property('use_default_controls',not self.data.hide_cursor) # display calculator for input def launch_numerical_input(self,callback="on_numerical_entry_return",data=None,data2=None,title=_("Entry dialog")): if self.data.entry_dialog: return label = gtk.Label(title) label.modify_font(pango.FontDescription("sans 20")) self.data.entry_dialog = gtk.Dialog(title, self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) calc = gladevcp.Calculator() calc.set_editable(True) self.data.entry_dialog.vbox.pack_start(label) self.data.entry_dialog.vbox.add(calc) calc.set_value("") calc.set_property("font","sans 20") calc.entry.connect("activate", lambda w : self.data.entry_dialog.emit('response',gtk.RESPONSE_ACCEPT)) self.data.entry_dialog.parse_geometry("400x400") #self.data.entry_dialog.set_decorated(False) if callback in dir(self.handler_instance): self.data.entry_dialog.connect("response", self.handler_instance[callback],calc,data,data2) else: self.data.entry_dialog.connect("response", self[callback],calc,data,data2) self.data.entry_dialog.show_all() def on_numerical_entry_return(self,widget,result,calc,userdata,userdata2): data = calc.get_value() if result == gtk.RESPONSE_ACCEPT: print "accept",data if data == None: data = 0 self.widgets.statusbar1.push(1,"Last Calculation: %f"%data) widget.destroy() self.data.entry_dialog = None def on_offset_origin_entry_return(self,widget,result,calc,userdata,userdata2): value = calc.get_value() if result == gtk.RESPONSE_ACCEPT: if value == None: return # if an axis is selected then set it for axis in self.data.axis_list: if self.widgets["axis_%s"%axis].get_active(): print "set %s axis" %axis if not axis == "s": if axis in('a','b','c'): pos = self.get_qualified_input(value,switch=_DEGREE_INPUT) else: pos = self.get_qualified_input(value) self.mdi_control.set_axis(axis,pos) self.reload_plot() widget.destroy() self.data.entry_dialog = None def on_tool_offset_entry_return(self,widget,result,calc,userdata,userdata2): value = calc.get_value() if result == gtk.RESPONSE_ACCEPT: if value == None: return # if an axis is selected then set it for axis in self.data.axis_list: if self.widgets["axis_%s"%axis].get_active(): print "tool %d, set in %s axis to- %f" %(self.data.tool_in_spindle,axis,value) if axis in('a','b','c'): pos = self.get_qualified_input(value,switch=_DEGREE_INPUT) else: pos = self.get_qualified_input(value) self.mdi_control.touchoff(self.data.tool_in_spindle,axis,pos) widget.destroy() self.data.entry_dialog = None def on_adj_overrides_entry_return(self,widget,result,calc,userdata,userdata2): data = calc.get_value() if result == gtk.RESPONSE_ACCEPT: print "accept",data if data == None: return None self.adjustment_buttons(userdata,userdata2,data) widget.destroy() self.data.entry_dialog = None # shows the cursor and warps it to the origin before exiting def hack_leave(self,*args): if not self.data.hide_cursor: return w = self.widgets.window1.window d = w.get_display() s = w.get_screen() x, y = w.get_origin() d.warp_pointer(s, x, y) def on_hide_cursor(self,*args): print "hide cursor change" if self.widgets.hide_cursor.get_active(): self.prefs.putpref('hide_cursor', True) self.data.hide_cursor = True self.widgets.window1.window.set_cursor(INVISABLE) else: self.prefs.putpref('hide_cursor', False) self.data.hide_cursor = False self.widgets.window1.window.set_cursor(None) # opens halshow def on_halshow(self,*args): print "halshow",TCLPATH p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH)) # opens the calibration program def on_calibration(self,*args): print "calibration --%s"% self.inipath p = os.popen("tclsh %s/bin/emccalib.tcl -- -ini %s > /dev/null &" % (TCLPATH,self.inipath),"w") # opens the linuxcnc status program def on_status(self,*args): p = os.popen("linuxcnctop > /dev/null &","w") # opens a halmeter def on_halmeter(self,*args): print "halmeter" p = os.popen("halmeter &") # opens the halscope def on_halscope(self,*args): p = os.popen("halscope > /dev/null &","w") def on_ladder(self,*args): if hal.component_exists('classicladder_rt'): p = os.popen("classicladder &","w") else: self.notify(_("INFO:"),_("Classicladder realtime component not detected"),INFO_ICON) self.add_alarm_entry(_("ladder not available - is the realtime component loaded?")) # estop machine before closing def on_window1_destroy(self, widget, data=None): print "estopping / killing gscreen" self.emc.machine_off(1) self.emc.estop(1) time.sleep(2) gtk.main_quit() def on_axis_selection_clicked(self,widget): self.update_active_axis_buttons(widget) def on_mode_clicked(self,widget,event): # only change machine modes on click if event.type == gtk.gdk.BUTTON_PRESS: a,b,c = self.data.mode_order self.data.mode_order = b,c,a label = self.data.mode_labels self.widgets.button_mode.set_label(label[self.data.mode_order[0]]) self.mode_changed(self.data.mode_order[0]) def on_button_show_offsets_clicked(self,widget): self.toggle_offset_view() # Horizontal buttons def on_button_home_all_clicked(self,widget): self.home_all() def on_button_unhome_all_clicked(self,widget): self.unhome_all() def on_button_home_axis_clicked(self,widget): self.home_selected() def on_button_unhome_axis_clicked(self,widget): self.unhome_selected() def on_button_toggle_readout_clicked(self,widget): self.dro_toggle() def on_button_jog_mode_clicked(self,widget): self.jog_mode() def on_button_select_system_clicked(self,widget): self.origin_system() def on_button_flood_coolant_clicked(self,widget): self.toggle_flood() def on_button_mist_coolant_clicked(self,widget): self.toggle_mist() def on_button_tool_editor_clicked(self,widget): self.reload_tooltable() def on_button_block_delete_clicked(self,widget): self.toggle_block_delete() def on_button_option_stop_clicked(self,widget): self.toggle_optional_stop() def on_button_next_tab_clicked(self,widget): self.next_tab() def on_button_overrides_clicked(self,widget,button): self.toggle_overrides(widget,button) def on_button_clear_view_clicked(self,widget): self.clear_plot() def on_graphic_overrides_clicked(self,widget,button): self.toggle_graphic_overrides(widget,button) # vertical buttons def on_button_plus_pressed(self,widget): self.adjustment_buttons(widget,True) def on_button_plus_released(self,widget): self.adjustment_buttons(widget,False) def on_button_minus_pressed(self,widget): self.adjustment_buttons(widget,True) def on_button_minus_released(self,widget): self.adjustment_buttons(widget,False) def on_offset_origin_clicked(self,widget): # adjust overrrides if self.widgets.button_override.get_active(): self.launch_numerical_input("on_adj_overrides_entry_return",widget,True,title=_("Override Entry")) # offset origin else: self.set_axis_checks() def on_move_to_clicked(self,widget): # Move-to button # manual mode and jog mode active if self.data.mode_order[0] == self.data._MAN and self.widgets.button_jog_mode.get_active(): self.launch_numerical_input("on_adj_overrides_entry_return",widget,True) def on_tool_touchoff_clicked(self,widget): print "touch" self.tool_touchoff_checks() def on_mode_select_clicked(self,widget,event): maxpage = self.widgets.notebook_main.get_n_pages() page = self.widgets.notebook_main.get_current_page() nextpage = page + 1 print "mode select",maxpage,page,nextpage if nextpage == maxpage:nextpage = 0 self.widgets.notebook_main.set_current_page(nextpage) def on_estop_clicked(self,*args): if self.data.estopped: self.emc.estop_reset(1) elif not self.data.machine_on: self.emc.machine_on(1) self.widgets.on_label.set_text("Machine On") self.add_alarm_entry(_("Machine powered on")) else: self.emc.machine_off(1) self.emc.estop(1) self.widgets.on_label.set_text("Machine Off") self.add_alarm_entry(_("Machine Estopped!")) def on_calc_clicked(self,widget): self.launch_numerical_input(title=_("Calculator")) def on_theme_choice_changed(self, widget): self.change_theme(widget.get_active_text()) # True is fullscreen def on_fullscreen1_pressed(self, widget): self.set_fullscreen1(widget.get_active()) def on_use_screen2_pressed(self,*args): self.toggle_screen2() # True is metric def on_dro_units_pressed(self, widget): self.set_dro_units(widget.get_active()) # True is diameter mode def on_diameter_mode_pressed(self, widget): self.set_diameter_mode(widget.get_active()) def on_rel_colorbutton_color_set(self,*args): self.set_rel_color() def on_abs_colorbutton_color_set(self,*args): self.set_abs_color() def on_dtg_colorbutton_color_set(self,*args): self.set_dtg_color() # True for showing full offsets def on_show_offsets_pressed(self, widget): self.set_show_offsets(widget.get_active()) def on_unlock_number_value_changed(self,widget): self.data.unlock_code = str(int(widget.get_value())) self.set_unlock_code() # True is for showing DTG def on_show_dtg_pressed(self, widget): self.set_show_dtg(widget.get_active()) # True will use notify def on_desktop_notify_toggled(self,widget): self.set_desktop_notify( widget.get_active()) def on_pop_statusbar_clicked(self, *args): self.widgets.statusbar1.pop(self.statusbar_id) # This is part of the user message system # There is status that prints to the status bar # There is Okdialog that prints a dialog that the user must acknoledge # there is yes/no dialog where the user must choose between yes or no # you can combine status and dialog messages so they print to the status bar # and pop a dialog def on_printmessage(self, pin, pinname,boldtext,text,type): if not pin.get(): return if boldtext == "NONE": boldtext = None if "status" in type: if boldtext: statustext = boldtext else: statustext = text self.notify(_("INFO:"),statustext,INFO_ICON) if "dialog" in type or "okdialog" in type: if pin.get(): self.halcomp[pinname + "-waiting"] = True if "okdialog" in type: self.warning_dialog(boldtext,True,text,pinname) else: if pin.get(): self.halcomp[pinname + "-response"] = 0 self.warning_dialog(boldtext,False,text,pinname) def toggle_overrides(self,widget,data): print "overrides - button_h_%s"% data list = ('jog_speed','jog_increments','feed_override','spindle_override','rapid_override') for i in (list): print i,data if i == data:continue button = "button_%s"% (i) print "block",button self.block(button) self.widgets[button].set_active(False) self.unblock(button) self.update_hal_override_pins() def toggle_graphic_overrides(self,widget,data): print "graphic overrides - button_%s"%data list = ('zoom','pan_v','pan_h','rotate_v','rotate_h') for i in (list): if i == data:continue button = "button_%s"% (i) self.block(button) self.widgets[button].set_active(False) self.unblock(button) def on_hal_status_interp_run(self,widget): print "run" self.sensitize_widgets(self.data.sensitive_run_idle,False) def on_hal_status_interp_idle(self,widget): print "idle" self.sensitize_widgets(self.data.sensitive_run_idle,True) state = self.data.all_homed self.sensitize_widgets(self.data.sensitive_all_homed,state) mode = self.emc.get_mode() print "mode",mode,self.data.mode_order[0] if self.data.mode_order[0] == self.data._MAN and not mode == 1: print "set to manual" self.emc.set_manual_mode() def on_hal_status_state_on(self,widget): print "on" self.sensitize_widgets(self.data.sensitive_on_off,True) state = self.data.all_homed self.sensitize_widgets(self.data.sensitive_all_homed,state) if not state: self.widgets.button_homing.emit("clicked") def on_hal_status_state_off(self,widget): print "off" self.sensitize_widgets(self.data.sensitive_on_off,False) def on_hal_status_axis_homed(self,widget,data): print "homed list",data temp=[] for letter in(self.data.axis_list): count = "xyzabcuvws".index(letter) if str(count) in data: temp.append(" %s"%letter.upper()) self.add_alarm_entry(_("Axes %s are homed"%temp)) def on_hal_status_all_homed(self,widget): print "all-homed" self.data.all_homed = True self.widgets.button_homing.set_active(False) self.widgets.statusbar1.remove_message(self.statusbar_id,self.homed_status_message) self.add_alarm_entry(_("All the axes have been homed")) def on_hal_status_not_all_homed(self,widget,data): print "not-all-homed",data self.data.all_homed = False temp =[] for letter in(self.data.axis_list): count = "xyzabcuvws".index(letter) if str(count) in data: temp.append(" %s"%letter.upper()) self.add_alarm_entry(_("There are unhomed axes: %s"%temp)) def on_hal_status_file_loaded(self,widget,filename): path,name = os.path.split(filename) self.widgets.gcode_tab.set_text(name) self.add_alarm_entry(_("Program loaded: %s"%filename)) def on_toggle_keyboard(self,widget,args="",x="",y=""): if self.data.ob: self.kill_keyboard() else: self.launch_keyboard() if self.data.mode_order[0] == self.data._MDI: try: self.widgets.hal_mdihistory.entry.grab_focus() except: dbg("**** GSCREEN ERROR: can't set focus to hal_mdihistory when Onboard launched - Is this widget name in glade file?") elif self.data.mode_order[0] == self.data._AUTO: try: self.widgets.gcode_view.grab_focus() except: dbg("**** GSCREEN ERROR: can't set focus to gcode_view when Onboard launched - Is this widget name in glade file?") def on_hal_jog_increments_changed(self,halpin): print halpin.get() data = halpin.get() self.set_jog_increments(vector=data) def on_hal_jog_rate_changed(self,halpin): print halpin.get() data = halpin.get() self.set_jog_rate(absolute=data) # highlight the gcode down one line lower # used for run-at-line restart def restart_down(self,widget,calc): self.widgets.gcode_view.line_down() line = int(self.widgets.gcode_view.get_line_number()) calc.set_value(line) self.update_restart_line(line) # highlight the gcode down one line higher # used for run-at-line restart def restart_up(self,widget,calc): self.widgets.gcode_view.line_up() line = int(self.widgets.gcode_view.get_line_number()) calc.set_value(line) self.update_restart_line(line) # highlight the gcode line specified # used for run-at-line restart def restart_set_line(self,widget,calc): try: line = int(calc.get_value()) except: calc.set_value("0.0") line = 0 self.widgets.gcode_view.set_line_number(line) self.update_restart_line(line) # This is a method that toggles the DRO units # the preference unit button saves the state # for startup, This one just changes it for the session def on_metric_select_clicked(self,widget): data = (self.data.dro_units -1) * -1 self.set_dro_units(data,False) def on_button_edit_clicked(self,widget): state = widget.get_active() if not state: self.edited_gcode_check() self.widgets.notebook_main.set_current_page(0) self.widgets.notebook_main.set_show_tabs(not (state)) self.edit_mode(state) if not state and self.widgets.button_full_view.get_active(): self.set_full_graphics_view(True) if state: self.widgets.search_box.show() else: self.widgets.search_box.hide() def on_button_change_view_clicked(self,widget): self.toggle_view() def on_button_full_view_clicked(self,widget): self.set_full_graphics_view(widget.get_active()) # ****** do stuff ***** def check_mode(self): try: return self.handler_instance.check_mode() except: pass string=[] if self.data.mode_order[0] == self.data._MAN and self.widgets.notebook_main.get_current_page() == 0: string.append( self.data._MAN) if self.widgets.button_jog_mode.get_active(): # jog mode active string.append(self.data._JOG) return string def spindle_dialog(self): if not self.data.spindle_control_dialog: self.data.spindle_control_dialog = gtk.Dialog(_("Manual Spindle Control"), self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CLOSE, gtk.RESPONSE_REJECT)) self.data.spindle_control_dialog.vbox.add(self.widgets.frame_s) self.data.spindle_control_dialog.parse_geometry("200x200") self.data.spindle_control_dialog.connect("delete_event", self.spindle_dialog_return) self.data.spindle_control_dialog.connect("response", self.spindle_dialog_return) self.data.spindle_control_dialog.show_all() def spindle_dialog_return(self,widget,signal): self.data.spindle_control_dialog.hide() return True def update_restart_line(self,line): if "set_restart_line" in dir(self.handler_instance): self.handler_instance.set_restart_line(line) else: self.set_restart_line(line) def set_restart_line(self,line): self.widgets.hal_toggleaction_run.set_restart_line(line) def edited_gcode_check(self): if self.widgets.gcode_view.buf.get_modified(): dialog = gtk.MessageDialog(self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,"You edited the File. save edits?\n Choosing No will erase the edits.") dialog.show_all() result = dialog.run() dialog.destroy() if result == gtk.RESPONSE_YES: self.widgets.hal_action_saveas.emit("activate") else: self.widgets.gcode_view.load_file() def set_desktop_notify(self,data): self.data.desktop_notify = data self.prefs.putpref('desktop_notify', data, bool) # shows 'Onboard' virtual keyboard if available # check for key_box widget - if there is, and embedded flag, embed Onboard in it. # else launch an independant Onboard inside a dialog so it works in fullscreen # (otherwise it hides when main screen is touched) # else error message def launch_keyboard(self,args="",x="",y=""): print args,x,y def dialog_keyboard(): if self.data.keyboard_dialog: self.data.keyboard_dialog.show() self.data.ob = True else: self.data.ob = subprocess.Popen(["onboard","--xid",args,x,y], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) sid = self.data.ob.stdout.readline() self.data.keyboard_dialog = gtk.Dialog(_("Keyboard"), self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT) self.data.keyboard_dialog.set_accept_focus(False) self.data.keyboard_dialog.set_deletable(False) socket = gtk.Socket() socket.show() self.data.keyboard_dialog.vbox.add(socket) socket.add_id(long(sid)) self.data.keyboard_dialog.parse_geometry("800x200") self.data.keyboard_dialog.show_all() self.data.keyboard_dialog.connect("destroy", self.keyboard_return) try: if self.widgets.key_box and self.data.embedded_keyboard: self.widgets.rightside_box.show() self.widgets.key_box.show() self.data.ob = subprocess.Popen(["onboard","--xid",args,x,y], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) sid = self.data.ob.stdout.readline() print"keyboard", sid # skip header line socket = gtk.Socket() socket.show() self.widgets.key_box.add(socket) socket.add_id(long(sid)) else: dialog_keyboard() except: try: dialog_keyboard() except: print _("Error with launching 'Onboard' on-screen keyboard program") # seems the only way to trap the destroy signal def keyboard_return(self,widget): self.data.keyboard_dialog = None self.data.ob = None # if keyboard in dialog just hide it # else kill it and if needed hide the key_box def kill_keyboard(self): if not self.data.keyboard_dialog == None: self.data.keyboard_dialog.hide() self.data.ob = None return try: self.widgets.key_box.hide() self.data.ob.kill() self.data.ob.terminate() self.data.ob = None except: try: self.data.ob.kill() self.data.ob.terminate() self.data.ob = None except: self.show_try_errors() # this installs local signals unless overriden by custom handlers # HAL pin signal call-backs are covered in the HAL pin initilization functions def connect_signals(self, handlers): signal_list = [ ["","button_estop","clicked", "on_estop_clicked"], ["","gremlin","motion-notify-event", "on_gremlin_motion"], ["","button_mode","button_press_event", "on_mode_clicked"], ["","button_menu","button_press_event", "on_mode_select_clicked"], ["","button_plus","pressed", "on_button_plus_pressed"], ["","button_plus","released", "on_button_plus_released"], ["","button_minus","pressed", "on_button_minus_pressed"], ["","button_minus","released", "on_button_minus_released"], ["","button_zero_origin","clicked", "adjustment_buttons",True], ["","button_offset_origin","clicked", "on_offset_origin_clicked"], ["","button_move_to","clicked", "on_move_to_clicked"], ["","button_tool_set","clicked", "on_tool_touchoff_clicked"], ["","button_change_view","clicked", "on_button_change_view_clicked"], ["","button_full_view","clicked", "on_button_full_view_clicked"], ["","button_home_all","clicked", "on_button_home_all_clicked"], ["","button_unhome_all","clicked", "on_button_unhome_all_clicked"], ["","button_home_axis","clicked", "on_button_home_axis_clicked"], ["","button_unhome_axis","clicked", "on_button_unhome_axis_clicked"], ["","button_toggle_readout","clicked", "on_button_toggle_readout_clicked"], ["","button_jog_mode","clicked", "on_button_jog_mode_clicked"], ["","button_spindle_controls","clicked", "on_button_spindle_controls_clicked"], ["","button_select_system","clicked", "on_button_select_system_clicked"], ["","button_mist_coolant","clicked", "on_button_mist_coolant_clicked"], ["","button_flood_coolant","clicked", "on_button_flood_coolant_clicked"], ["","button_tool_editor","clicked", "on_button_tool_editor_clicked"], ["","button_toggle_readout2","clicked", "on_button_toggle_readout_clicked"], ["","button_show_offsets","clicked", "on_button_show_offsets_clicked"], ["","button_block_delete","clicked", "on_button_block_delete_clicked"], ["","button_option_stop","clicked", "on_button_option_stop_clicked"], ["","button_next_tab","clicked", "on_button_next_tab_clicked"], ["","button_calc","clicked", "on_calc_clicked"], ["block","button_jog_speed","clicked", "on_button_overrides_clicked","jog_speed"], ["","button_select_rotary_adjust","clicked", "on_button_select_rotary_adjust_clicked"], ["block","button_jog_increments","clicked", "on_button_overrides_clicked","jog_increments"], ["block","button_feed_override","clicked", "on_button_overrides_clicked","feed_override"], ["block","button_spindle_override","clicked", "on_button_overrides_clicked","spindle_override"], ["block","button_rapid_override","clicked", "on_button_overrides_clicked","rapid_override"], ["block","button_zoom","clicked", "on_graphic_overrides_clicked","zoom"], ["block","button_pan_v","clicked", "on_graphic_overrides_clicked","pan_v"], ["block","button_pan_h","clicked", "on_graphic_overrides_clicked","pan_h"], ["block","button_rotate_v","clicked", "on_graphic_overrides_clicked","rotate_v"], ["block","button_rotate_h","clicked", "on_graphic_overrides_clicked","rotate_h"], ["","button_clear_view","clicked", "on_button_clear_view_clicked"], ["","theme_choice","changed", "on_theme_choice_changed"], ["","use_screen2","clicked", "on_use_screen2_pressed"], ["","dro_units","clicked", "on_dro_units_pressed"], ["","diameter_mode","clicked", "on_diameter_mode_pressed"], ["","button_edit","toggled", "on_button_edit_clicked"], ["","show_offsets","clicked", "on_show_offsets_pressed"], ["","show_dtg","clicked", "on_show_dtg_pressed"], ["","fullscreen1","clicked", "on_fullscreen1_pressed"], ["","shut_down","clicked", "on_window1_destroy"], ["","shut_down",'released',"hack_leave"], ["","run_halshow","clicked", "on_halshow"], ["","run_calibration","clicked", "on_calibration"], ["","run_status","clicked", "on_status"], ["","run_halmeter","clicked", "on_halmeter"], ["","run_halscope","clicked", "on_halscope"], ["","run_ladder","clicked", "on_ladder"], ["","hide_cursor","clicked", "on_hide_cursor"], ["","button_homing","clicked", "homing"], ["","button_override","clicked", "override"], ["","button_graphics","clicked", "graphics"], ["","desktop_notify","toggled", "on_desktop_notify_toggled"], ["","grid_size","value_changed", "set_grid_size"], ["","spindle_start_rpm","value_changed", "set_spindle_start_rpm"], ["","spindle_control","clicked", "on_spindle_control_clicked"], ["","spindle_preset","clicked", "on_preset_spindle"], ["","spindle_increase","clicked", "on_spindle_speed_adjust"], ["","spindle_decrease","clicked", "on_spindle_speed_adjust"], ["","audio_error_chooser","update-preview", "update_preview"], ["","audio_alert_chooser","update-preview", "update_preview"], ["","hal_status","interp-idle", "on_hal_status_interp_idle"], ["","hal_status","interp-run", "on_hal_status_interp_run"], ["","hal_status","state-on", "on_hal_status_state_on"], ["","hal_status","state-off", "on_hal_status_state_off"], ["","hal_status","homed", "on_hal_status_axis_homed"], ["","hal_status","all-homed", "on_hal_status_all_homed"], ["","hal_status","not-all-homed", "on_hal_status_not_all_homed"], ["","hal_status","file-loaded", "on_hal_status_file_loaded"], ["","window1","destroy", "on_window1_destroy"], ["","pop_statusbar","clicked", "on_pop_statusbar_clicked"], ["","dtg_colorbutton","color-set", "on_dtg_colorbutton_color_set"], ["","abs_colorbutton","color-set", "on_abs_colorbutton_color_set"], ["","rel_colorbutton","color-set", "on_rel_colorbutton_color_set"], ["","eventbox_gremlin","leave_notify_event", "on_eventbox_gremlin_leave_notify_event"], ["","eventbox_gremlin","enter_notify_event", "on_eventbox_gremlin_enter_notify_event"], ["block","s_display_rev","toggled", "on_s_display_rev_toggled"], ["block","s_display_fwd","toggled", "on_s_display_fwd_toggled"], ["","ignore_limits","clicked", "toggle_ignore_limits"], ["","audio_error_chooser","selection_changed","change_sound","error"], ["","audio_alert_chooser","selection_changed","change_sound","alert"], ["","toggle_keyboard","clicked", "on_toggle_keyboard"], ["","metric_select","clicked","on_metric_select_clicked"], ["","button_restart","clicked", "launch_restart_dialog"], ["","button_index_tool","clicked", "on_index_tool"], ["","button_search_fwd","clicked", "search_fwd"], ["","button_search_bwd","clicked", "search_bwd"], ["","button_undo","clicked", "undo_edit"], ["","button_redo","clicked", "redo_edit"],] # check to see if the calls in the signal list are in the custom handler's list of calls # if so skip the call in the signal list # else connect the signals based on how many arguments they have and if blockable for i in signal_list: if i[3] in handlers: print _("**** GSCREEN INFO: Overriding internal signal call to %s"% i[3]) continue try: # add id # for blockable signals if i[0] == "block": j = "_sighandler_%s"% i[1] if len(i) == 4: self.data[j] = int(self.widgets[i[1]].connect(i[2], self[i[3]])) if len(i) == 5: self.data[j] = int(self.widgets[i[1]].connect(i[2], self[i[3]],i[4])) elif len(i) == 4: self.widgets[i[1]].connect(i[2], self[i[3]]) elif len(i) == 5: self.widgets[i[1]].connect(i[2], self[i[3]],i[4]) except: print ("**** GSCREEN WARNING: could not connect %s to %s"% (i[1],i[3])) # setup signals that can be blocked but not overriden for axis in self.data.axis_list: cb = "axis_%s"% axis i = "_sighandler_axis_%s"% axis try: self.data[i] = int(self.widgets[cb].connect("clicked", self.on_axis_selection_clicked)) except: self.show_try_errors() def toggle_offset_view(self): data = self.data.plot_hidden data = (data * -1) +1 self.widgets.dro_frame.set_visible(not data) self.widgets.gremlin.set_property('enable_dro', data) self.widgets.gremlin.set_property('show_program', not data) self.widgets.gremlin.set_property('show_limits', not data) self.widgets.gremlin.set_property('show_extents_option', not data) self.widgets.gremlin.set_property('show_live_plot', not data) self.widgets.gremlin.set_property('show_tool', not data) self.widgets.gremlin.show_offsets = data self.data.plot_hidden = data def preset_spindle_speed(self,rpm): self.data.spindle_preset = rpm self.widgets.spindle_preset.set_label(" S %d"% rpm) def sensitize_widgets(self, widgetlist, value): for name in widgetlist: try: self.widgets[name].set_sensitive(value) except: print "**** GSCREEN WARNING: No widget named: %s to sensitize"%name def from_internal_linear_unit(self,v, unit=None): if unit is None: unit = self.status.get_linear_units() lu = (unit or 1) * 25.4 return v*lu def parse_increment(self,jogincr): if jogincr.endswith("mm"): scale = self.from_internal_linear_unit(1/25.4) elif jogincr.endswith("cm"): scale = self.from_internal_linear_unit(10/25.4) elif jogincr.endswith("um"): scale = self.from_internal_linear_unit(.001/25.4) elif jogincr.endswith("in") or jogincr.endswith("inch"): scale = self.from_internal_linear_unit(1.) elif jogincr.endswith("mil"): scale = self.from_internal_linear_unit(.001) else: scale = 1 jogincr = jogincr.rstrip(" inchmuil") if "/" in jogincr: p, q = jogincr.split("/") jogincr = float(p) / float(q) else: jogincr = float(jogincr) return jogincr * scale # This prints a message in the status bar, the system notifier (if available) # and makes a sound (if available) # It returns a statusbar message id reference so one can directly erase the message later. # Ubuntu screws with the system notification program so it does follow timeouts # There is a ppa on the net to fix this I suggest it. # https://launchpad.net/~leolik/+archive/leolik?field.series_filter=lucid def notify(self,title,message,icon="",timeout=2): messageid = None try: messageid = self.widgets.statusbar1.push(self.statusbar_id,message) except: self.show_try_errors() self.add_alarm_entry(message) if NOTIFY_AVAILABLE and self.data.desktop_notify: uri = "" if icon: uri = "file://" + icon n = pynotify.Notification(title, message, uri) n.set_hint_string("x-canonical-append","True") n.set_urgency(pynotify.URGENCY_CRITICAL) n.set_timeout(int(timeout * 1000) ) n.show() if _AUDIO_AVAILABLE: if icon == ALERT_ICON: self.audio.set_sound(self.data.error_sound) else: self.audio.set_sound(self.data.alert_sound) self.audio.run() return messageid def add_alarm_entry(self,message): try: textbuffer = self.widgets.alarm_history.get_buffer() textbuffer.insert_at_cursor(strftime("%a, %d %b %Y %H:%M:%S -", localtime())+message+"\n" ) except: self.show_try_errors() def next_tab(self): maxpage = self.widgets.notebook_mode.get_n_pages() page = self.widgets.notebook_mode.get_current_page() nextpage = page + 1 print "mode select",maxpage,page,nextpage if nextpage == maxpage:nextpage = 0 self.widgets.notebook_mode.set_current_page(nextpage) def set_feed_override(self,percent_rate,absolute=False): if absolute: rate = percent_rate else: rate = self.data.feed_override + percent_rate if rate > self.data.feed_override_max: rate = self.data.feed_override_max self.emc.feed_override(rate) def set_spindle_override(self,percent_rate,absolute=False): if absolute: rate = percent_rate else: rate = self.data.spindle_override + percent_rate if rate > self.data.spindle_override_max: rate = self.data.spindle_override_max elif rate < self.data.spindle_override_min: rate = self.data.spindle_override_min self.emc.spindle_override(rate) def set_velocity_override(self,percent_rate,absolute=False): if absolute: rate = percent_rate else: rate = self.data.velocity_override + percent_rate if rate > 1.0: rate = 1.0 self.emc.max_velocity(rate * self.data._maxvelocity) def set_jog_rate(self,step=None,absolute=None): if self.data.angular_jog_adjustment_flag: j_rate = "angular_jog_rate" else: j_rate = "jog_rate" # in units per minute print "jog rate =",step,absolute,self.data[j_rate] if not absolute == None: rate = absolute elif not step == None: rate = self.data[j_rate] + step else:return if rate < 0: rate = 0 if rate > self.data[j_rate+"_max"]: rate = self.data[j_rate+"_max"] rate = round(rate,1) if self.data.angular_jog_adjustment_flag: self.emc.continuous_jog_velocity(None,rate) else: self.emc.continuous_jog_velocity(rate,None) self.data[j_rate] = rate # This sets the jog increments -there are three ways # ABSOLUTE: # set absolute to the absolute increment wanted # INDEX from INI: # self.data.jog_increments holds the increments from the INI file # do not set absolute variable # index_dir = 1 or -1 to set the rate higher or lower from the list def set_jog_increments(self,vector=None,index_dir=None,absolute=None): print "set jog incr" if self.data.angular_jog_adjustment_flag: incr = "angular_jog_increments" incr_index = "current_angular_jogincr_index" else: incr = "jog_increments" incr_index = "current_jogincr_index" if not absolute == None: distance = absolute self.widgets[incr].set_text("%f"%distance) self.halcomp["jog-increment-out"] = distance print "index jog increments",distance return elif not index_dir == None: next = self.data[incr_index] + index_dir elif not vector == None: next = vector else: return end = len(self.data[incr])-1 if next < 0: next = 0 if next > end: next = end self.data[incr_index] = next jogincr = self.data[incr][next] try: if 'angular' in incr and not jogincr == 'continuous': label = jogincr + ' Degs' else: label = jogincr self.widgets[incr].set_text(label) except: self.show_try_errors() if jogincr == ("continuous"): distance = 0 else: distance = self.parse_increment(jogincr) print "index jog increments",jogincr,distance self.halcomp["jog-increment-out"] = distance def adjustment_buttons(self,widget,action,change=0): print "adjustment buttons" # is over ride adjustment selection active? if self.widgets.button_override.get_active(): print "override" if widget == self.widgets.button_zero_origin: print "zero button",action change = 0 absolute = True elif widget == self.widgets.button_offset_origin: print "set at button",action absolute = True elif widget == self.widgets.button_plus: print "up button",action change = 1 absolute = False elif widget == self.widgets.button_minus: print "down button",action change = -1 absolute = False else:return self.adjust_overrides(widget,action,change,absolute) # graphics adjustment elif self.widgets.button_graphics.get_active(): inc = self.data.graphic_move_inc if widget == self.widgets.button_plus: print "up button",action change = 1 elif widget == self.widgets.button_minus: print "down button",action change = -1 if self.widgets.button_zoom.get_active() and action: print "zoom" if change == 1: self.zoom_in() else: self.zoom_out() elif self.widgets.button_pan_v.get_active() and action: print "pan vertical" self.widgets.gremlin.set_mouse_start(0,0) if change == 1: self.pan(0,-inc) else: self.pan(0,inc) elif self.widgets.button_pan_h.get_active() and action: print "pan horizontal" self.widgets.gremlin.set_mouse_start(0,0) if change == 1: self.pan(-inc,0) else: self.pan(inc,0) elif self.widgets.button_rotate_v.get_active() and action: print "rotate horiontal" self.widgets.gremlin.set_mouse_start(0,0) if change == 1: self.rotate(-inc,0) else: self.rotate(inc,0) elif self.widgets.button_rotate_h.get_active() and action: print "rotate horiontal" self.widgets.gremlin.set_mouse_start(0,0) if change == 1: self.rotate(0,-inc) else: self.rotate(0,inc) # user coordinate system elif self.widgets.button_select_system.get_active(): if widget == self.widgets.button_plus and action: print "up button",action change = 1 elif widget == self.widgets.button_minus and action: print "down button",action change = -1 else: return self.change_origin_system(None,change) # Jogging mode (This needs to be last) elif self.data.mode_order[0] == self.data._MAN and self.widgets.button_jog_mode.get_active(): # manual mode and jog mode active # what axis is set if widget == self.widgets.button_zero_origin: print "zero button",action self.zero_axis() elif widget == self.widgets.button_move_to: print "move to button",action self.move_to(change) elif widget == self.widgets.button_plus: print "up button",action self.do_jog(True,action) elif widget == self.widgets.button_minus: print "down button",action self.do_jog(False,action) elif widget == self.widgets.button_offset_origin: self.set_axis_checks() elif widget == self.widgets.button_zero_origin: print "zero buttons" self.zero_axis() elif widget == self.widgets.button_offset_origin: print "set axis buttons" self.set_axis_checks() def adjust_overrides(self,widget,action,number,absolute): print "adjust overrides",action,number,absolute # what override is selected if absolute: change = self.get_qualified_input(number,_PERCENT_INPUT)/100 else: change = number if self.widgets.button_feed_override.get_active() and action: print "feed override" if absolute: self.set_feed_override(change,absolute) else: self.set_feed_override((change * self.data.feed_override_inc),absolute) elif self.widgets.button_spindle_override.get_active() and action: print "spindle override" if absolute: self.set_spindle_override(change,absolute) else: self.set_spindle_override((change * self.data.spindle_override_inc),absolute) elif self.widgets.button_rapid_override.get_active() and action: print "velocity override" if absolute: self.set_velocity_override(change,absolute) else: self.set_velocity_override((change * self.data.velocity_override_inc),absolute) elif self.widgets.button_jog_speed.get_active() and action: print "jog speed adjustment" if widget == self.widgets.button_offset_origin: change = self.get_qualified_input(number) if absolute: self.set_jog_rate(absolute = change) else: if self.data.angular_jog_adjustment_flag: self.set_jog_rate(step = (change * self.data.angular_jog_rate_inc)) else: self.set_jog_rate(step = (change * self.data.jog_rate_inc)) elif self.widgets.button_jog_increments.get_active() and action: print "jog increments adjustment" if widget == self.widgets.button_offset_origin: change = self.get_qualified_input(number) if absolute: self.set_jog_increments(absolute = change) else: self.set_jog_increments(index_dir = change) def origin_system(self,*args): print "origin system button" value = self.widgets.button_select_system.get_active() self.sensitize_widgets(self.data.sensitive_origin_mode,not value) def change_origin_system(self,system,direction=None): print system,direction system_list = (0,54,55,56,57,58,59,59.1,59.2,59.3) current = system_list[self.data.system] if not system: if direction > 0 and not current == 59.3: self.mdi_control.set_user_system(system_list[self.data.system+1]) elif direction < 0 and not current == 54: self.mdi_control.set_user_system(system_list[self.data.system-1]) self.reload_plot() def homing(self,*args): print "show/hide homing buttons" if self.widgets.button_homing.get_active(): if len(self.data.active_axis_buttons) > 1: for i in self.data.axis_list: self.widgets["axis_%s"%i].set_active(False) for i in ('zero_origin','offset_origin','plus','minus'): self.widgets["button_%s"% i].set_sensitive(False) self.widgets.mode0.hide() self.widgets.mode3.show() #self.widgets.button_mode.set_sensitive(False) self.widgets.button_override.set_sensitive(False) self.widgets.button_graphics.set_sensitive(False) else: for i in ('zero_origin','offset_origin','plus','minus'): self.widgets["button_%s"% i].set_sensitive(True) self.widgets.mode3.hide() self.widgets.mode0.show() state = self.data.all_homed self.sensitize_widgets(self.data.sensitive_all_homed,state) self.widgets.button_override.set_sensitive(True) self.widgets.button_graphics.set_sensitive(True) def graphics(self,*args): print "show/hide graphics buttons" if self.widgets.button_graphics.get_active(): for i in range(0,3): self.widgets["mode%d"% i].hide() self.widgets.mode5.show() self.widgets.vmode0.show() self.widgets.vmode1.hide() self._tempholder = [] for name in (self.data.sensitive_graphics_mode): self._tempholder.append(self.widgets[name].get_sensitive()) self.widgets[name].set_sensitive(False) self.widgets.vmode0.set_sensitive(True) self.widgets.button_plus.set_sensitive(True) self.widgets.button_minus.set_sensitive(True) else: self.widgets.mode5.hide() self.mode_changed(self.data.mode_order[0]) for num,name in enumerate(self.data.sensitive_graphics_mode): if self.data.machine_on: self.widgets[name].set_sensitive(True) else: self.widgets[name].set_sensitive(self._tempholder[num]) def override(self,*args): print "show/hide override buttons" value = self.widgets.button_override.get_active() self.sensitize_widgets(self.data.sensitive_override_mode,not value) if self.widgets.button_override.get_active(): for i in range(0,3): self.widgets["mode%d"% i].hide() self.widgets.mode4.show() self.widgets.vmode0.show() self.widgets.vmode1.hide() self.widgets.button_zero_origin.set_label("Zero\n ") self.widgets.button_offset_origin.set_label("Set At\n ") else: self.widgets.mode4.hide() self.mode_changed(self.data.mode_order[0]) self.widgets.button_zero_origin.set_label(_(" Zero Origin")) self.widgets.button_offset_origin.set_label(_("Offset Origin")) # search for and set up user requested message system. # status displays on the statusbat and requires no acknowledge. # dialog displays a GTK dialog box with yes or no buttons # okdialog displays a GTK dialog box with an ok button # dialogs require an answer before focus is sent back to main screen def message_setup(self): if not self.inifile: return m_boldtext = self.inifile.findall("DISPLAY", "MESSAGE_BOLDTEXT") m_text = self.inifile.findall("DISPLAY", "MESSAGE_TEXT") m_type = self.inifile.findall("DISPLAY", "MESSAGE_TYPE") m_pinname = self.inifile.findall("DISPLAY", "MESSAGE_PINNAME") if len(m_text) != len(m_type): print _("**** Gscreen ERROR: Invalid message configuration (missing text or type) in INI File [DISPLAY] section") if len(m_text) != len(m_pinname): print _("**** Gscreen ERROR: Invalid message configuration (missing pinname) in INI File [DISPLAY] section") if len(m_text) != len(m_boldtext): print _("**** Gscreen ERROR: Invalid message configuration (missing boldtext) in INI File [DISPLAY] section") for bt,t,c ,name in zip(m_boldtext,m_text, m_type,m_pinname): #print bt,t,c,name if not ("status" in c) and not ("dialog" in c) and not ("okdialog" in c): print _("**** Gscreen ERROR: invalid message type (%s)in INI File [DISPLAY] section"% c) continue if not name == None: # this is how we make a pin that can be connected to a callback self.data['name'] = hal_glib.GPin(self.halcomp.newpin(name, hal.HAL_BIT, hal.HAL_IN)) self.data['name'].connect('value-changed', self.on_printmessage,name,bt,t,c) if ("dialog" in c): self.halcomp.newpin(name+"-waiting", hal.HAL_BIT, hal.HAL_OUT) if not ("ok" in c): self.halcomp.newpin(name+"-response", hal.HAL_BIT, hal.HAL_OUT) # display dialog def warning_dialog(self,message, displaytype, secondary=None,pinname=None): if displaytype: dialog = gtk.MessageDialog(self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK,message) else: dialog = gtk.MessageDialog(self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,message) # if there is a secondary message then the first message text is bold if secondary: dialog.format_secondary_text(secondary) dialog.show_all() try: if "dialog_return" in dir(self.handler_instance): dialog.connect("response", self.handler_instance.dialog_return,self,displaytype,pinname) else: dialog.connect("response", self.dialog_return,displaytype,pinname) except: dialog.destroy() raise NameError (_('Dialog error - Is the dialog handler missing from the handler file?')) if pinname == "TOOLCHANGE": dialog.set_title(_("Manual Toolchange")) else: dialog.set_title(_("Operator Message")) # message dialog returns a response here # This includes the manual tool change dialog # We know this by the pinname being called 'TOOLCHANGE' def dialog_return(self,widget,result,dialogtype,pinname): if pinname == "TOOLCHANGE": self.halcomp["tool-changed"] = True widget.destroy() try: self.widgets.statusbar1.remove_message(self.statusbar_id,self.data.tool_message) except: self.show_try_errors() return if not dialogtype: # yes/no dialog if result == gtk.RESPONSE_YES:result = True else: result = False if pinname: self.halcomp[pinname + "-response"] = result if pinname: self.halcomp[pinname + "-waiting"] = False widget.destroy() # dialog is used for choosing the run-at-line position def launch_restart_dialog(self,widget): self.restart_dialog() # dialog for manually calling a tool def restart_dialog(self): if self.data.restart_dialog: return if "restart_dialog_return" in dir(self.handler_instance): return_method = self.handler_instance.restart_dialog_return else: return_method = self.restart_dialog_return self.data.restart_dialog = gtk.Dialog(_("Restart Entry"), self.widgets.window1, gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) label = gtk.Label(_("Restart Entry")) label.modify_font(pango.FontDescription("sans 20")) self.data.restart_dialog.vbox.pack_start(label) calc = gladevcp.Calculator() self.data.restart_dialog.vbox.add(calc) calc.set_value("%d"%self.data.last_line) calc.set_property("font","sans 20") calc.set_editable(True) box = gtk.HButtonBox() upbutton = gtk.Button(label = _("Up")) box.add(upbutton) enterbutton = gtk.Button(label = _("Enter")) box.add(enterbutton) downbutton = gtk.Button(label = _("Down")) box.add(downbutton) calc.calc_box.pack_end(box, expand=False, fill=False, padding=0) upbutton.connect("clicked",self.restart_up,calc) downbutton.connect("clicked",self.restart_down,calc) enterbutton.connect("clicked",lambda w:calc.entry.emit('activate')) calc.entry.connect("activate",return_method,True,calc) self.data.restart_dialog.parse_geometry("400x400+0+0") self.data.restart_dialog.show_all() calc.num_pad_only(True) calc.integer_entry_only(True) self.data.restart_dialog.connect("response", return_method,calc) # either start the gcode at the line specified or cancel def restart_dialog_return(self,widget,result,calc): value = 0 if not result == gtk.RESPONSE_REJECT: value = calc.get_value() if value == None:value = 0 self.widgets.gcode_view.set_line_number(value) self.add_alarm_entry(_("Ready to Restart program from line %d"%value)) self.update_restart_line(value) self.data.restart_dialog.destroy() self.data.restart_dialog = None # adds the embedded object to a notebook tab or box def _dynamic_tab(self, widget, text): s = gtk.Socket() try: widget.append_page(s, gtk.Label(" " + text + " ")) except: try: widget.pack_end(s,True,True,0) except: return None return s.get_id() # Check INI file for embed commands # NAME is used as the tab label if a notebook is used # LOCATION is the widgets name from the gladefile. # COMMAND is the actual program command # if no location is specified the main notebook is used def set_dynamic_tabs(self): from subprocess import Popen if not self.inifile: return tab_names = self.inifile.findall("DISPLAY", "EMBED_TAB_NAME") tab_location = self.inifile.findall("DISPLAY", "EMBED_TAB_LOCATION") tab_cmd = self.inifile.findall("DISPLAY", "EMBED_TAB_COMMAND") if len(tab_names) != len(tab_cmd): print _("Invalid embeded tab configuration") # Complain somehow if len(tab_location) != len(tab_names): for num,i in enumerate(tab_names): try: if tab_location[num]: continue except: tab_location.append("notebook_mode") for t,c ,name in zip(tab_names, tab_cmd,tab_location): nb = self.widgets[name] xid = self._dynamic_tab(nb, t) if not xid: continue cmd = c.replace('{XID}', str(xid)) child = Popen(cmd.split()) self._dynamic_childs[xid] = child nb.show_all() # Gotta kill the embedded processes when gscreen closes def kill_dynamic_childs(self): for c in self._dynamic_childs.values(): c.terminate() # finds the postgui file name and INI file path def postgui(self): postgui_halfile = self.inifile.find("HAL", "POSTGUI_HALFILE") return postgui_halfile,sys.argv[2] # zooms in a set amount (set deep in gremlin) def zoom_in(self,*args): self.widgets.gremlin.zoom_in() def zoom_out(self,*args): self.widgets.gremlin.zoom_out() def set_fullscreen1(self, data): self.prefs.putpref('fullscreen1', data, bool) self.data.fullscreen1 = data if data: self.widgets.window1.fullscreen() else: self.widgets.window1.unfullscreen() def set_show_offsets(self, data): self.prefs.putpref('show_offsets', data, bool) self.data.show_offsets = data try: self.widgets.gremlin.show_offsets = data except: self.show_try_errors() def set_show_dtg(self, data): self.prefs.putpref('show_dtg', data, bool) try: self.widgets.gremlin.set_property('show_dtg',data) except: self.show_try_errors() def set_diameter_mode(self, data): print "toggle diameter mode" self.data.diameter_mode = data self.prefs.putpref('diameter_mode', data, bool) try: self.widgets.gremlin.set_property('show_lathe_radius',not data) except: self.show_try_errors() # 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)) def set_rel_color(self): self.data.rel_color = self.convert_to_rgb(self.widgets.rel_colorbutton.get_color()) self.prefs.putpref('rel_textcolor', self.widgets.rel_colorbutton.get_color(),str) def set_abs_color(self): self.data.abs_color = self.convert_to_rgb(self.widgets.abs_colorbutton.get_color()) self.prefs.putpref('abs_textcolor', self.widgets.abs_colorbutton.get_color(),str) def set_dtg_color(self): self.data.dtg_color = self.convert_to_rgb(self.widgets.dtg_colorbutton.get_color()) self.prefs.putpref('dtg_textcolor', self.widgets.dtg_colorbutton.get_color(),str) def set_unlock_code(self): self.prefs.putpref('unlock_code', self.data.unlock_code,str) # toggles gremlin's different views # if in lathe mode only P, Y and Y2 available def toggle_view(self): dist = self.widgets.gremlin.get_zoom_distance() def shift(): a = self.data.plot_view[0] b = self.data.plot_view[1] c = self.data.plot_view[2] d = self.data.plot_view[3] e = self.data.plot_view[4] f = self.data.plot_view[5] self.data.plot_view = (b,c,d,e,f,a) shift() if self.data.lathe_mode: while not self.data.plot_view[0].lower() in("p","y","y2"): shift() elif self.data.plot_view[0].lower() == "y2": shift() self.widgets.gremlin.set_property('view',self.data.plot_view[0]) self.prefs.putpref('view', self.data.plot_view, tuple) self.widgets.gremlin.set_zoom_distance(dist) # toggle a large graphics view / gcode view def set_full_graphics_view(self,data): print "full view",data if data: print "enlarge" self.data.full_graphics = True self.widgets.notebook_mode.hide() self.widgets.dro_frame.hide() self.widgets.gremlin.set_property('enable_dro',True) else: print "shrink" self.data.full_graphics = False self.widgets.notebook_mode.show() self.widgets.dro_frame.show() self.widgets.gremlin.set_property('enable_dro',False) # enlargen the Gcode box while in edit mode def edit_mode(self,data): print "edit mode pressed",data self.sensitize_widgets(self.data.sensitive_edit_mode,not data) if data: self.widgets.mode2.hide() self.widgets.mode6.show() self.widgets.dro_frame.hide() self.widgets.gcode_view.set_sensitive(1) self.data.edit_mode = True self.widgets.show_box.hide() self.widgets.notebook_mode.show() else: self.widgets.mode6.hide() self.widgets.mode2.show() self.widgets.dro_frame.show() self.widgets.gcode_view.set_sensitive(0) self.data.edit_mode = False self.widgets.show_box.show() def set_dro_units(self, data, save=True): print "toggle dro units",self.data.dro_units,data if data == self.data._IMPERIAL: print "switch to imperial" self.status.dro_inch(1) self.widgets.gremlin.set_property('metric_units',False) try: self.widgets.offsetpage1.set_to_inch() except: self.show_try_errors() else: print "switch to mm" self.status.dro_mm(1) self.widgets.gremlin.set_property('metric_units',True) try: self.widgets.offsetpage1.set_to_mm() except: self.show_try_errors() self.data.dro_units = data if save: self.prefs.putpref('dro_is_metric', data, bool) def toggle_optional_stop(self): print "option stop" self.set_optional_stop(self.widgets.button_option_stop.get_active()) def set_optional_stop(self,data): self.prefs.putpref('opstop', data, bool) self.data.op_stop = data self.emc.opstop(data) def toggle_block_delete(self): self.set_block_delete(self.widgets.button_block_delete.get_active()) def set_block_delete(self,data): print "block delete" self.prefs.putpref('blockdel', data, bool) self.data.block_del = data self.emc.blockdel(data) def save_edit(self): print "edit" # helper method to block and unblock GTK widget signals def block(self,widget_name): self.widgets["%s"%(widget_name)].handler_block(self.data["_sighandler_%s"% (widget_name)]) def unblock(self,widget_name): self.widgets["%s"%(widget_name)].handler_unblock(self.data["_sighandler_%s"% (widget_name)]) # update the global variable of active axis buttons # if in jogging or homing mode, only one axis can be active at once # update the related axis HAL pins def update_active_axis_buttons(self,widget): count = 0;temp = [] self.data.active_axis_buttons = [] for i in self.data.axis_list: num = "xyzabcuvws".index(i) if self.widgets.button_jog_mode.get_active() or self.widgets.button_homing.get_active(): if not self.widgets["axis_%s"%i] == widget: # unselect axis / HAL pin self.block("axis_%s"%i) self.widgets["axis_%s"%i].set_active(False) self.unblock("axis_%s"%i) continue if self.widgets["axis_%s"%i].get_active(): count +=1 axisnum = num self.data.active_axis_buttons.append((i,num)) if count == 0: self.data.active_axis_buttons.append((None,None)) # check and update jogging buttons self.jog_mode() # adjust sensitivity and labels of buttons def jog_mode(self): print "jog mode:",self.widgets.button_jog_mode.get_active() # if muliple axis selected - unselect all of them if len(self.data.active_axis_buttons) > 1 and self.widgets.button_jog_mode.get_active(): for i in self.data.axis_list: self.widgets["axis_%s"%i].set_active(False) if self.widgets.button_jog_mode.get_active(): self.widgets.button_move_to.set_label("Goto Position") self.emc.set_manual_mode() else: self.widgets.button_move_to.set_label("") self.update_hal_jog_pins() self.update_hal_override_pins() # do some checks then jog selected axis or start spindle def do_jog(self,direction,action): # if manual mode, if jogging # if only one axis button pressed # jog positive at selected rate if self.data.mode_order[0] == self.data._MAN: if len(self.data.active_axis_buttons) > 1: self.notify(_("INFO:"),_("Can't jog multiple axis"),INFO_ICON) print self.data.active_axis_buttons elif self.data.active_axis_buttons[0][0] == None: self.notify(_("INFO:"),_("No axis selected to jog"),INFO_ICON) else: print "Jog axis %s" % self.data.active_axis_buttons[0][0] if not self.data.active_axis_buttons[0][0] == "s": if not action: cmd = 0 elif direction: cmd = 1 else: cmd = -1 self.emc.jogging(1) if self.data.active_axis_buttons[0][0] in('a','b','c'): jogincr = self.data.angular_jog_increments[self.data.current_angular_jogincr_index] else: jogincr = self.data.jog_increments[self.data.current_jogincr_index] print jogincr if jogincr == ("continuous"): # continuous jog print "active axis jog:",self.data.active_axis_buttons[0][1] self.emc.continuous_jog(self.data.active_axis_buttons[0][1],cmd) else: print "jog incremental" if cmd == 0: return # don't want release of button to stop jog distance = self.parse_increment(jogincr) self.emc.incremental_jog(self.data.active_axis_buttons[0][1],cmd,distance) def do_key_jog(self,axis,direction,action): if self.data._JOG in self.check_mode(): # jog mode active: if not action: cmd = 0 elif direction: cmd = 1 else: cmd = -1 self.emc.jogging(1) print self.data.jog_increments[self.data.current_jogincr_index] if self.data.jog_increments[self.data.current_jogincr_index] == ("continuous"): # continuous jog print "active axis jog:",axis self.emc.continuous_jog(axis,cmd) else: print "jog incremental" if cmd == 0: return # don't want release of button to stop jog self.mdi_control.mdi.emcstat.poll() if self.mdi_control.mdi.emcstat.state != 1: return jogincr = self.data.jog_increments[self.data.current_jogincr_index] distance = self.parse_increment(jogincr) self.emc.incremental_jog(axis,cmd,distance) # spindle control def spindle_adjustment(self,direction,action): if action and not self.widgets.s_display_fwd.get_active() and not self.widgets.s_display_rev.get_active(): self.notify(_("INFO:"),_("No direction selected for spindle"),INFO_ICON) return if direction and action: if self.data.spindle_speed: self.emc.spindle_faster(1) elif self.widgets.s_display_fwd.get_active(): self.emc.spindle_forward(1,self.data.spindle_start_rpm) else: self.emc.spindle_reverse(1,self.data.spindle_start_rpm) print direction,action elif not direction and action: if self.data.spindle_speed: if self.data.spindle_speed >100: self.emc.spindle_slower(1) else: self.emc.spindle_off(1) # feeds to a position (while in manual mode) def do_jog_to_position(self,data): if len(self.data.active_axis_buttons) > 1: self.notify(_("INFO:"),_("Can't jog multiple axis"),INFO_ICON) print self.data.active_axis_buttons elif self.data.active_axis_buttons[0][0] == None: self.notify(_("INFO:"),_("No axis selected to move"),INFO_ICON) else: if not self.data.active_axis_buttons[0][0] == "s": if self.data.active_axis_buttons[0][0] in('a','b','c'): rate = self.data.angular_jog_rate pos = self.get_qualified_input(data,switch=_DEGREE_INPUT) else: rate = self.data.jog_rate pos = self.get_qualified_input(data) self.mdi_control.go_to_position(self.data.active_axis_buttons[0][0],pos,rate) def adjust_spindle_rpm(self, rpm, direction=None): # spindle control if direction == None: direction = self.data.spindle_dir if direction > 0: print "forward" self.emc.spindle_forward(1, float(rpm)) elif direction < 0: print "reverse" self.emc.spindle_reverse(1, float(rpm)) else: self.emc.spindle_off(1) # shows the second glade file panel def toggle_screen2(self): self.data.use_screen2 = self.widgets.use_screen2.get_active() if self.screen2: if self.data.use_screen2: self.widgets.window2.show() else: self.widgets.window2.hide() self.prefs.putpref('use_screen2', self.data.use_screen2, bool) # This converts and qualifies the input # eg for diameter, metric or percentage def get_qualified_input(self,raw = 0,switch = None): print "RAW input:",raw if switch in(_DEGREE_INPUT, _SPINDLE_INPUT): return raw elif switch == _PERCENT_INPUT: return round(raw,2) else: g21 = False if "G21" in self.data.active_gcodes: g21 = True # metric DRO - imperial mode if self.data.dro_units == self.data._MM: if not g21: raw = raw / 25.4 # imperial DRO - metric mode elif g21: raw = raw * 25.4 if switch == "x" and self.data.diameter_mode: print "convert from diameter" raw = raw / 2.0 print "Qualified input:",raw return raw def unhome_all(self): self.emc.unhome_all(1) def home_all(self): self.emc.home_all(1) # do some checks first the home the selected axis def home_selected(self): print "home selected" if len(self.data.active_axis_buttons) > 1: self.notify(_("INFO:"),_("Can't home multiple axis - select HOME ALL instead"),INFO_ICON) print self.data.active_axis_buttons elif self.data.active_axis_buttons[0][0] == None: self.notify(_("INFO:"),_("No axis selected to home"),INFO_ICON) else: print "home axis %s" % self.data.active_axis_buttons[0][0] self.emc.home_selected(self.data.active_axis_buttons[0][1]) def unhome_selected(self): if len(self.data.active_axis_buttons) > 1: self.notify(_("INFO:"),_("Can't unhome multiple axis"),INFO_ICON) print self.data.active_axis_buttons elif self.data.active_axis_buttons[0][0] == None: self.notify(_("INFO:"),_("No axis selected to unhome"),INFO_ICON) else: print "unhome axis %s" % self.data.active_axis_buttons[0][0] self.emc.unhome_selected(self.data.active_axis_buttons[0][1]) # Touchoff the axis zeroing it # reload the plot to update the display def zero_axis(self): if self.data.active_axis_buttons[0][0] == None: self.notify(_("INFO:"),_("No axis selected for origin zeroing"),INFO_ICON) # if an axis is selected then set it for i in self.data.axis_list: if self.widgets["axis_%s"%i].get_active(): print "zero %s axis" %i self.mdi_control.set_axis(i,0) self.reload_plot() # touchoff - setting the axis to the input def set_axis_checks(self): if self.data.active_axis_buttons[0][0] == None: self.notify(_("INFO:"),_("No axis selected for origin touch-off"),INFO_ICON) return self.launch_numerical_input("on_offset_origin_entry_return") def tool_touchoff_checks(self): if len(self.data.active_axis_buttons) > 1: self.notify(_("INFO:"),_("Can't tool touch-off multiple axes"),INFO_ICON) return if self.data.active_axis_buttons[0][0] == None: self.notify(_("INFO:"),_("No axis selected for tool touch-off"),INFO_ICON) return self.launch_numerical_input("on_tool_offset_entry_return") # move axis to a position (while in manual mode) def move_to(self,data): if self.data.mode_order[0] == self.data._MAN:# if in manual mode if self.widgets.button_jog_mode.get_active(): # jog mode active print "jog to position" self.do_jog_to_position(data) def clear_plot(self): self.widgets.gremlin.clear_live_plotter() def pan(self,x,y): self.widgets.gremlin.pan(x,y) def rotate(self,x,y): self.widgets.gremlin.rotate_view(x,y) def reload_plot(self): print "reload plot" self.widgets.hal_action_reload.emit("activate") def toggle_mist(self): if self.data.mist: self.emc.mist_off(1) else: self.emc.mist_on(1) def toggle_flood(self): if self.data.flood: self.emc.flood_off(1) else: self.emc.flood_on(1) def toggle_ignore_limits(self,*args): print "over ride limits" self.emc.override_limits(1) # toggle the tool editor page forward # reload the page when doing this # If the user specified a tool editor spawn it. def reload_tooltable(self): # show the tool table page or return to the main page if not self.widgets.notebook_main.get_current_page() == 3: self.widgets.notebook_main.set_current_page(3) else: self.widgets.notebook_main.set_current_page(0) return # set the tooltable path from the INI file and reload it path = os.path.join(CONFIGPATH,self.data.tooltable) print "tooltable:",path self.widgets.tooledit1.set_filename(path) # see if user requested an external editor and spawn it editor = self.data.tooleditor if not editor == None: res = os.spawnvp(os.P_WAIT, editor, [editor, path]) if res: self.notify(_("Error Message"),_("Tool editor error - is the %s editor available?"% editor,ALERT_ICON,3)) # tell linuxcnc that the tooltable may have changed self.emc.reload_tooltable(1) # toggle thru the DRO large display def dro_toggle(self): print "toggle axis display" a = self.data.display_order[0] b = self.data.display_order[1] c = self.data.display_order[2] self.data.display_order = (c,a,b) self.prefs.putpref('display_order', self.data.display_order, tuple) if self.data.display_order[2] == _ABS: self.widgets.gremlin.set_property('use_relative',False) else: self.widgets.gremlin.set_property('use_relative',True) # adjust the screen as per each mode toggled def mode_changed(self,mode): if mode == self.data._MAN: self.widgets.vmode0.show() self.widgets.vmode1.hide() self.widgets.notebook_mode.hide() self.widgets.hal_mdihistory.hide() self.widgets.button_homing.show() self.widgets.dro_frame.show() self.widgets.spare.hide() elif mode == self.data._MDI: if self.widgets.button_homing.get_active(): self.widgets.button_homing.emit("clicked") if self.data.plot_hidden: self.toggle_offset_view() self.emc.set_mdi_mode() self.widgets.hal_mdihistory.show() self.widgets.vmode0.show() self.widgets.vmode1.hide() self.widgets.notebook_mode.hide() elif mode == self.data._AUTO: self.widgets.vmode0.hide() self.widgets.vmode1.show() if self.data.full_graphics: self.widgets.notebook_mode.hide() else: self.widgets.notebook_mode.show() self.widgets.hal_mdihistory.hide() if not mode == self.data._MAN: self.widgets.button_jog_mode.set_active(False) self.widgets.button_homing.set_active(False) self.widgets.button_homing.hide() self.widgets.spare.show() for i in range(0,3): if i == mode: self.widgets["mode%d"% i].show() else: self.widgets["mode%d"% i].hide() def change_theme(self, theme): self.prefs.putpref('gtk_theme', theme, str) if theme == None:return if theme == "Follow System Theme": theme = self.data.system_theme settings = gtk.settings_get_default() settings.set_string_property("gtk-theme-name", theme, "") # check linuxcnc for status, error and then update the readout def timer_interrupt(self): self.emc.mask() self.emcstat = linuxcnc.stat() self.emcerror = linuxcnc.error_channel() self.emcstat.poll() self.data.task_mode = self.emcstat.task_mode self.status.periodic() self.data.system = self.status.get_current_system() e = self.emcerror.poll() if e: kind, text = e print kind,text if "joint" in text: for letter in self.data.axis_list: axnum = "xyzabcuvws".index(letter) text = text.replace( "joint %d"%axnum,"Axis %s"%letter.upper() ) if kind in (linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR): self.notify(_("Error Message"),text,ALERT_ICON,3) elif kind in (linuxcnc.NML_TEXT, linuxcnc.OPERATOR_TEXT): self.notify(_("Message"),text,INFO_ICON,3) elif kind in (linuxcnc.NML_DISPLAY, linuxcnc.OPERATOR_DISPLAY): self.notify(_("Message"),text,INFO_ICON,3) self.emc.unmask() if "periodic" in dir(self.handler_instance): self.handler_instance.periodic() else: self.update_position() return True # update the whole display def update_position(self,*args): self.update_mdi_spindle_button() self.update_spindle_bar() self.update_dro() self.update_active_gcodes() self.update_active_mcodes() self.update_aux_coolant_pins() self.update_feed_speed_label() self.update_tool_label() self.update_coolant_leds() self.update_estop_led() self.update_machine_on_led() self.update_limit_override() self.update_override_label() self.update_jog_rate_label() self.update_mode_label() self.update_units_button_label() # spindle controls def update_mdi_spindle_button(self): try: self.widgets.at_speed_label.set_label(_("%d RPM"%abs(self.data.spindle_speed))) except: pass label = self.widgets.spindle_control.get_label() speed = self.data.spindle_speed if speed == 0 and not label == _("Start"): temp = _("Start") elif speed and not label == _("Stop"): temp = _("Stop") else: return self.widgets.spindle_control.set_label(temp) def update_spindle_bar(self): self.widgets.s_display.set_value(abs(self.halcomp["spindle-readout-in"])) self.widgets.s_display.set_target_value(abs(self.data.spindle_speed)) try: self.widgets.s_display2.set_value(abs(self.data.spindle_speed)) except: self.show_try_errors() def update_dro(self): # DRO for i in self.data.axis_list: for j in range (0,3): current = self.data.display_order[j] attr = pango.AttrList() if current == _ABS: color = self.data.abs_color data = self.data["%s_abs"%i] #text = "%+ 10.4f"% self.data["%s_abs"%i] label = "ABS" elif current == _REL: color = self.data.rel_color data = self.data["%s_rel"%i] #text = "%+ 10.4f"% self.data["%s_rel"%i] label= "REL" elif current == _DTG: color = self.data.dtg_color data = self.data["%s_dtg"%i] #text = "%+ 10.4f"% self.data["%s_dtg"%i] label = "DTG" if j == 2: if self.data.highlight_major: hlcolor = self.data.highlight_color bg_color = pango.AttrBackground(hlcolor[0],hlcolor[1],hlcolor[2], 0, -1) attr.insert(bg_color) size = pango.AttrSize(30000, 0, -1) attr.insert(size) weight = pango.AttrWeight(600, 0, -1) attr.insert(weight) fg_color = pango.AttrForeground(color[0],color[1],color[2], 0, 11) attr.insert(fg_color) self.widgets["%s_display_%d"%(i,j)].set_attributes(attr) h = " " if current == _ABS and self.data["%s_is_homed"% i]: h = "*" if self.data.diameter_mode and i == 'x': data = data * 2.0 if self.data.dro_units == self.data._MM: text = "%s% 10.3f"% (h,data) else: text = "%s% 9.4f"% (h,data) self.widgets["%s_display_%d"%(i,j)].set_text(text) self.widgets["%s_display_%d"%(i,j)].set_alignment(0,.5) self.widgets["%s_display_%d_label"%(i,j)].set_alignment(1,.5) self.widgets["%s_display_%d_label"%(i,j)].set_text(label) def update_active_gcodes(self): # active codes active_g = " ".join(self.data.active_gcodes) self.widgets.active_gcodes_label.set_label("%s "% active_g) def update_active_mcodes(self): self.widgets.active_mcodes_label.set_label(" ".join(self.data.active_mcodes)) def update_aux_coolant_pins(self): # control aux_coolant - For Dave Armstrong m7 = m8 = False self.halcomp["aux-coolant-m8-out"] = False self.halcomp["mist-coolant-out"] = False self.halcomp["aux-coolant-m7-out"] = False self.halcomp["flood-coolant-out"] = False if self.data.mist: if self.widgets.aux_coolant_m7.get_active(): self.halcomp["aux-coolant-m7-out"] = True else: self.halcomp["mist-coolant-out"] = True if self.data.flood: if self.widgets.aux_coolant_m8.get_active(): self.halcomp["aux-coolant-m8-out"] = True else: self.halcomp["flood-coolant-out"] = True def update_feed_speed_label(self): data = self.data.velocity if self.data.IPR_mode: try: data = data/abs(self.halcomp["spindle-readout-in"]) except: data = 0 if self.data.dro_units == self.data._MM: text = "%.2f"% (data) else: text = "%.3f"% (data) self.widgets.active_feed_speed_label.set_label("F%s S%s V%s"% (self.data.active_feed_command, self.data.active_spindle_command,text)) def update_tool_label(self): # corodinate system: systemlabel = (_("Machine"),"G54","G55","G56","G57","G58","G59","G59.1","G59.2","G59.3") tool = str(self.data.tool_in_spindle) if tool == None: tool = "None" self.widgets.system.set_text(("Tool %s %s"%(tool,systemlabel[self.data.system]))) def update_coolant_leds(self): # coolant self.widgets.led_mist.set_active(self.data.mist) self.widgets.led_flood.set_active(self.data.flood) def update_estop_led(self): # estop self.widgets.led_estop.set_active(self.data.estopped) def update_machine_on_led(self): self.widgets.led_on.set_active(self.data.machine_on) def update_limit_override(self): # ignore limts led self.widgets.led_ignore_limits.set_active(self.data.or_limits) def update_override_label(self): # overrides self.widgets.fo.set_text("FO: %d%%"%(round(self.data.feed_override,2)*100)) self.widgets.so.set_text("SO: %d%%"%(round(self.data.spindle_override,2)*100)) self.widgets.mv.set_text("VO: %d%%"%(round((self.data.velocity_override),2) *100)) # we need to check if the current units is in the basic machine units - convert if nesassary. # then set the display according to the current display units. def update_jog_rate_label(self): rate = round(self.status.convert_units(self.data.jog_rate),2) if self.data.dro_units == self.data._MM: text = "%4.2f mm/min"% (rate) else: text = "%3.2f IPM"% (rate) self.widgets.jog_rate.set_text(text) try: text = "%4.2f DPM"% (self.data.angular_jog_rate) self.widgets.angular_jog_rate.set_text(text) except: pass def update_mode_label(self): # Mode / view modenames = self.data.mode_labels time = strftime("%a, %d %b %Y %I:%M:%S %P ", localtime()) self.widgets.mode_label.set_label( "%s View -%s %s"% (modenames[self.data.mode_order[0]],self.data.plot_view[0],time) ) def update_units_button_label(self): label = self.widgets.metric_select.get_label() data = self.data.dro_units if data and not label == " mm ": temp = " mm " elif data == 0 and not label == "Inch": temp = "Inch" else: return self.widgets.metric_select.set_label(temp) def update_hal_jog_pins(self): for i in self.data.axis_list: if self.widgets.button_jog_mode.get_active() and self.widgets["axis_%s"%i].get_active(): self.halcomp["jog-enable-%s-out"%i] = True else: self.halcomp["jog-enable-%s-out"%i] = False if self.widgets.button_jog_mode.get_active(): self.halcomp["jog-enable-out"] = True else: self.halcomp["jog-enable-out"] = False try: self.widgets.led_jog_mode.set_active(self.halcomp["jog-enable-out"]) except: pass # These pins set and unset enable pins for override adjustment # only true when the screen button is true and not in jog mode # (because jog mode may use the encoder for jogging) def update_hal_override_pins(self): jogmode = not(self.widgets.button_jog_mode.get_active()) fo = self.widgets.button_feed_override.get_active() and jogmode so = self.widgets.button_spindle_override.get_active() and jogmode mv = self.widgets.button_rapid_override.get_active() and jogmode self.halcomp["f-override-enable-out"] = fo self.halcomp["s-override-enable-out"] = so self.halcomp["mv-override-enable-out"] = mv def __getitem__(self, item): return getattr(self, item) def __setitem__(self, item, value): return setattr(self, item, value) # calls a postgui file if there is one. # then starts Gscreen if __name__ == "__main__": try: print "**** GSCREEN INFO ini:", sys.argv[2] app = Gscreen() except KeyboardInterrupt: sys.exit(0) postgui_halfile,inifile = Gscreen.postgui(app) print "**** GSCREEN INFO: postgui filename:",postgui_halfile if postgui_halfile: res = os.spawnvp(os.P_WAIT, "halcmd", ["halcmd", "-i",inifile,"-f", postgui_halfile]) if res: raise SystemExit, res gtk.main()