/ lib / python / gladevcp / macro_widget.py
macro_widget.py
  1  #!/usr/bin/env python
  2  # vim: sts=4 sw=4 et
  3  # GladeVcp Macro widget
  4  #
  5  # Based on hal MDI history widget
  6  # Copyright (c) 2011  Pavel Shramov <shramov@mexmat.net>
  7  #
  8  # This program is free software: you can redistribute it and/or modify
  9  # it under the terms of the GNU General Public License as published by
 10  # the Free Software Foundation, either version 2 of the License, or
 11  # (at your option) any later version.
 12  #
 13  # This program is distributed in the hope that it will be useful,
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16  # GNU General Public License for more details.
 17  
 18  import os, time, string
 19  
 20  import gobject, gtk
 21  
 22  from hal_widgets import _HalWidgetBase
 23  import linuxcnc
 24  from hal_glib import GStat
 25  from hal_actions import _EMC_ActionBase, ensure_mode
 26  # path to TCL for external programs eg. halshow
 27  try:
 28      TCLPATH = os.environ['LINUXCNC_TCL_DIR']
 29  except:
 30      pass
 31  
 32  class MacroSelect(gtk.VBox, _EMC_ActionBase):
 33      __gtype_name__ = 'MacroSelect'
 34      __gsignals__ = {
 35                      'macro-submitted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,gobject.TYPE_STRING,)),
 36                      }
 37  
 38      def __init__(self, *a, **kw):
 39          gtk.VBox.__init__(self, *a, **kw)
 40          self.gstat = GStat()
 41          # if 'NO_FORCE_HOMING' is true, MDI  commands are allowed before homing.
 42          try:
 43              inifile = os.environ.get('INI_FILE_NAME', '/dev/null')
 44              self.ini = linuxcnc.ini(inifile)
 45              no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0)
 46              macros =  self.inifile.findall("MACROS", "MACRO")
 47              sub_path = self.inifile.find("RS274NGC", "SUBROUTINE_PATH")or '~/linuxcnc/nc_files/macros'
 48          except:
 49              no_home_required = 1
 50              macros = None
 51              sub_path = '~/linuxcnc/nc_files/macros'
 52  
 53          #path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history'
 54          self.foldername = os.path.expanduser(sub_path)
 55  
 56          self.model = gtk.ListStore(str)
 57  
 58          self.tv = gtk.TreeView()
 59          self.tv.set_model(self.model)
 60          self.cell = gtk.CellRendererText()
 61  
 62          self.col = gtk.TreeViewColumn("Macro Commands")
 63          self.col.pack_start(self.cell, True)
 64          self.col.add_attribute(self.cell, 'text', 0)
 65  
 66          self.tv.append_column(self.col)
 67          self.tv.set_search_column(0)
 68          self.tv.set_reorderable(False)
 69          self.tv.set_headers_visible(True)
 70  
 71          scroll = gtk.ScrolledWindow()
 72          scroll.add(self.tv)
 73          scroll.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC
 74          scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
 75  
 76          self.entry = gtk.Entry()
 77          self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'gtk-ok')
 78  
 79          self.entry.connect('activate', self.submit)
 80          self.entry.connect('icon-press', self.submit)
 81          self.tv.connect('cursor-changed', self.select)
 82          self.tv.connect('key_press_event', self.on_key_press_event)
 83          self.tv.connect('button_press_event', self.on_button_press_event)
 84  
 85          self.pack_start(scroll, True)
 86          self.pack_start(self.entry, False)
 87          self.gstat.connect('state-off', lambda w: self.set_sensitive(False))
 88          self.gstat.connect('state-estop', lambda w: self.set_sensitive(False))
 89          self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on() and ( self.is_all_homed() or no_home_required ) ))
 90          self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode()))
 91          self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on()))
 92          self.reload()
 93          self.show_all()
 94  
 95      def reload(self):
 96          self.model.clear()
 97          files = []
 98          try:
 99              for f in os.listdir(self.foldername):
100                  if f.endswith('.ngc'):
101                      with open(os.path.join(self.foldername, f), 'r') as temp:
102                          first_line = temp.readline().strip()
103                          print first_line
104                          if 'MACROCOMMAND' in first_line:
105                              files.append(first_line.strip('; MACROCOMMAND='))
106          except:
107              pass
108          lines = filter(bool, files)
109          for l in lines:
110              self.model.append((l,))
111          path = (len(lines)-1,)
112          self.tv.scroll_to_cell(path)
113          self.tv.set_cursor(path)
114          self.entry.set_text('')
115  
116      def submit(self, *a):
117          cmd = self.entry.get_text()
118          if cmd == 'HALMETER':
119              self.load_halmeter()
120              return
121          elif cmd == 'STATUS':
122              self.load_status()
123              return
124          elif cmd == 'HALSHOW':
125              self.load_halshow()
126              return
127          if not cmd:
128              return
129          #ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI)
130          name = cmd.split()
131          path = self.foldername+ "/" + name[0] + ".ngc"
132          self.emit('macro-submitted',path,cmd)
133  
134          #self.linuxcnc.mdi(cmd)
135  
136          self.entry.set_text('')
137          self.entry.grab_focus()
138  
139      def select(self, w):
140          self.entry.set_text('')
141  
142      def on_key_press_event(self,w,event):
143          idx = w.get_cursor()[0]
144          if idx is None:
145              return True
146          if gtk.gdk.keyval_name(event.keyval) == 'Return':
147              self.entry.set_text(self.model[idx][0])
148              self.entry.grab_focus()
149              return True
150  
151      def on_button_press_event(self,w,event):
152          idx = w.get_cursor()[0]
153          if idx is None:
154              return True
155          self.entry.set_text(self.model[idx][0])
156  
157      def load_halmeter(self):
158          p = os.popen("halmeter &")
159      def load_status(self):
160          p = os.popen("linuxcnctop  > /dev/null &","w")
161      def load_halshow(self):
162          try:
163              p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH))
164          except:
165              self.entry.set_text('ERROR loading halshow')
166  
167  # for testing without glade editor:
168  # Must linuxcnc running to see anything
169  def main(filename = None):
170      def macro_callback(widget,path,cmd):
171          print cmd,path
172  
173      window = gtk.Dialog("Macro Test dialog",
174                     None,
175                     gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
176                     (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
177                      gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
178      widget = MacroSelect()
179      widget.connect("macro-submitted",macro_callback)
180      window.vbox.add(widget)
181      window.connect("destroy", gtk.main_quit)
182      window.show_all()
183      response = window.run()
184      if response == gtk.RESPONSE_ACCEPT:
185         print "True"
186      else:
187         print "False"
188  
189  if __name__ == "__main__":
190      main()
191