linuxcnc/lib/python/gladevcp/macro_widget.py

200 lines
6.8 KiB
Python

#!/usr/bin/env python3
# vim: sts=4 sw=4 et
# GladeVcp Macro widget
#
# Based on hal MDI history widget
# Copyright (c) 2011 Pavel Shramov <shramov@mexmat.net>
#
# 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.
import os, time, string
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject
import linuxcnc
from hal_glib import GStat
if __name__ == "__main__":
from hal_actions import _EMC_ActionBase, ensure_mode
from hal_widgets import _HalWidgetBase
else:
from .hal_actions import _EMC_ActionBase, ensure_mode
from .hal_widgets import _HalWidgetBase
# path to TCL for external programs eg. halshow
try:
TCLPATH = os.environ['LINUXCNC_TCL_DIR']
except:
pass
class MacroSelect(Gtk.VBox, _EMC_ActionBase):
__gtype_name__ = 'MacroSelect'
__gsignals__ = {
'macro-submitted': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING,GObject.TYPE_STRING,)),
}
def __init__(self, *a, **kw):
Gtk.VBox.__init__(self, *a, **kw)
self.gstat = GStat()
# if 'NO_FORCE_HOMING' is true, MDI commands are allowed before homing.
try:
inifile = os.environ.get('INI_FILE_NAME', '/dev/null')
self.ini = linuxcnc.ini(inifile)
no_home_required = int(self.ini.find("TRAJ", "NO_FORCE_HOMING") or 0)
macros = self.inifile.findall("MACROS", "MACRO")
sub_path = self.inifile.find("RS274NGC", "SUBROUTINE_PATH")or '~/linuxcnc/nc_files/macros'
except:
no_home_required = 1
macros = None
sub_path = '~/linuxcnc/nc_files/macros'
#path = self.ini.find('DISPLAY', 'MDI_HISTORY_FILE') or '~/.axis_mdi_history'
self.foldername = os.path.expanduser(sub_path)
self.model = Gtk.ListStore(str)
self.tv = Gtk.TreeView()
self.tv.set_model(self.model)
self.cell = Gtk.CellRendererText()
self.col = Gtk.TreeViewColumn("Macro Commands")
self.col.pack_start(self.cell, True)
self.col.add_attribute(self.cell, 'text', 0)
self.tv.append_column(self.col)
self.tv.set_search_column(0)
self.tv.set_reorderable(False)
self.tv.set_headers_visible(True)
scroll = Gtk.ScrolledWindow()
scroll.add(self.tv)
scroll.props.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC
scroll.props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC
self.entry = Gtk.Entry()
self.entry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, 'Gtk-ok')
self.entry.connect('activate', self.submit)
self.entry.connect('icon-press', self.submit)
self.tv.connect('cursor-changed', self.select)
self.tv.connect('key_press_event', self.on_key_press_event)
self.tv.connect('button_press_event', self.on_button_press_event)
self.pack_start(scroll, True, True, 0)
self.pack_start(self.entry, False, False, 0)
self.gstat.connect('state-off', lambda w: self.set_sensitive(False))
self.gstat.connect('state-estop', lambda w: self.set_sensitive(False))
self.gstat.connect('interp-idle', lambda w: self.set_sensitive(self.machine_on() and ( self.is_all_homed() or no_home_required ) ))
self.gstat.connect('interp-run', lambda w: self.set_sensitive(not self.is_auto_mode()))
self.gstat.connect('all-homed', lambda w: self.set_sensitive(self.machine_on()))
self.reload()
self.show_all()
def reload(self):
self.model.clear()
files = []
try:
for f in os.listdir(self.foldername):
if f.endswith('.ngc'):
with open(os.path.join(self.foldername, f), 'r') as temp:
first_line = temp.readline().strip()
print(first_line)
if 'MACROCOMMAND' in first_line:
files.append(first_line.strip('; MACROCOMMAND='))
except:
pass
lines = list(filter(bool, files))
for l in lines:
self.model.append((l,))
path = (len(lines)-1,)
self.tv.scroll_to_cell(path)
self.tv.set_cursor(path)
self.entry.set_text('')
def submit(self, *a):
cmd = self.entry.get_text()
if cmd == 'HALMETER':
self.load_halmeter()
return
elif cmd == 'STATUS':
self.load_status()
return
elif cmd == 'HALSHOW':
self.load_halshow()
return
if not cmd:
return
#ensure_mode(self.stat, self.linuxcnc, linuxcnc.MODE_MDI)
name = cmd.split()
path = self.foldername+ "/" + name[0] + ".ngc"
self.emit('macro-submitted',path,cmd)
#self.linuxcnc.mdi(cmd)
self.entry.set_text('')
self.entry.grab_focus()
def select(self, w):
self.entry.set_text('')
def on_key_press_event(self,w,event):
idx = w.get_cursor()[0]
if idx is None:
return True
if gdk.keyval_name(event.keyval) == 'Return':
self.entry.set_text(self.model[idx][0])
self.entry.grab_focus()
return True
def on_button_press_event(self,w,event):
idx = w.get_cursor()[0]
if idx is None:
return True
self.entry.set_text(self.model[idx][0])
def load_halmeter(self):
p = os.popen("halmeter &")
def load_status(self):
p = os.popen("linuxcnctop > /dev/null &","w")
def load_halshow(self):
try:
p = os.popen("tclsh %s/bin/halshow.tcl &" % (TCLPATH))
except:
self.entry.set_text('ERROR loading halshow')
# for testing without glade editor:
# Must linuxcnc running to see anything
def main(filename = None):
def macro_callback(widget,path,cmd):
print(cmd,path)
window = Gtk.Dialog("Macro Test dialog",
None,
Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT,
Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT))
widget = MacroSelect()
widget.connect("macro-submitted",macro_callback)
window.vbox.add(widget)
window.connect("destroy", Gtk.main_quit)
window.show_all()
response = window.run()
if response == Gtk.ResponseType.ACCEPT:
print("True")
else:
print("False")
if __name__ == "__main__":
main()