From e5db0287c1d29d1548f0855f5e2cf01b87ba9b77 Mon Sep 17 00:00:00 2001
From: Norbert Schechner <nieson@web.de>
Date: Thu, 24 Apr 2014 21:06:52 +0200
Subject: gladevcp - offsetpage-widget converted line delimiter to UNIX
 standard

---
 lib/python/gladevcp/offsetpage_widget.py | 1186 +++++++++++++++---------------
 1 file changed, 593 insertions(+), 593 deletions(-)

(limited to 'lib')

diff --git a/lib/python/gladevcp/offsetpage_widget.py b/lib/python/gladevcp/offsetpage_widget.py
index 84bed8ae9..37af00ad1 100755
--- a/lib/python/gladevcp/offsetpage_widget.py
+++ b/lib/python/gladevcp/offsetpage_widget.py
@@ -1,593 +1,593 @@
-#!/usr/bin/env python
-# GladeVcp Widget - offsetpage
-#
-# Copyright (c) 2013 Chris Morley
-#
-# 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.
-
-# This widget reads the offsets for current tool, current G5x, G92 using python library linuxcnc.
-# all other offsets are read directly from the Var file, if available, as linuxcnc does not give
-# access to all offsets thru NML, only current ones.
-# you can hide any axes or any columns
-# set metric or imperial
-# set the var file to search
-# set the text formatting for metric/imperial separately
-
-import sys, os, pango, linuxcnc
-from hal_glib import GStat
-datadir = os.path.abspath(os.path.dirname(__file__))
-AXISLIST = ['offset', 'X', 'Y', 'Z', 'A', 'B', 'C', 'U', 'V', 'W', 'name']
-# we need to know if linuxcnc isn't running when using the GLADE editor
-# as it causes big delays in response
-lncnc_running = False
-try:
-    import gobject, gtk
-except:
-    print('GTK not available')
-    sys.exit(1)
-
-# localization
-import locale
-BASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ".."))
-LOCALEDIR = os.path.join(BASE, "share", "locale")
-locale.setlocale(locale.LC_ALL, '')
-
-# we put this in a try so there is no error in the glade editor
-# linuxcnc is probably not running then
-try:
-    INIPATH = os.environ['INI_FILE_NAME']
-except:
-    pass
-
-class OffsetPage(gtk.VBox):
-    __gtype_name__ = 'OffsetPage'
-    __gproperties__ = {
-        'display_units_mm' : (gobject.TYPE_BOOLEAN, 'Display Units', 'Display in metric or not',
-                    False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
-        'mm_text_template' : (gobject.TYPE_STRING, 'Text template for Metric Units',
-                'Text template to display. Python formatting may be used for one variable',
-                "%10.3f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
-        'imperial_text_template' : (gobject.TYPE_STRING, 'Text template for Imperial Units',
-                'Text template to display. Python formatting may be used for one variable',
-                "%9.4f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
-        'font' : (gobject.TYPE_STRING, 'Pango Font', 'Display font to use',
-                "sans 12", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
-        'highlight_color'  : (gtk.gdk.Color.__gtype__, 'Highlight color', "",
-                    gobject.PARAM_READWRITE),
-        'foreground_color'  : (gtk.gdk.Color.__gtype__, 'Active text color', "",
-                    gobject.PARAM_READWRITE),
-        'hide_columns' : (gobject.TYPE_STRING, 'Hidden Columns', 'A no-spaces list of axes to hide: xyzabcuvw and t are the options',
-                    "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
-        'hide_rows' : (gobject.TYPE_STRING, 'Hidden Rows', 'A no-spaces list of rows to hide: 0123456789abc are the options' ,
-                    "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
-    }
-    __gproperties = __gproperties__
-
-    __gsignals__ = {
-                    'selection_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING,)),
-                   }
-
-
-    def __init__(self, filename = None, *a, **kw):
-        super(OffsetPage, self).__init__()
-        self.gstat = GStat()
-        self.filename = filename
-        self.linuxcnc = linuxcnc
-        self.status = linuxcnc.stat()
-        self.cmd = linuxcnc.command()
-        self.hash_check = None
-        self.display_units_mm = 0 # imperial
-        self.machine_units_mm = 0 # imperial
-        self.program_units = 0 # imperial
-        self.display_follows_program = False # display units are chosen indepenadently of G20/G21
-        self.font = "sans 12"
-        self.editing_mode = False
-        self.highlight_color = gtk.gdk.Color("lightblue")
-        self.foreground_color = gtk.gdk.Color("red")
-        self.unselectable_color = gtk.gdk.Color("lightgray")
-        self.hidejointslist = []
-        self.hidecollist = []
-        self.wTree = gtk.Builder()
-        self.wTree.set_translation_domain("linuxcnc") # for locale translations
-        self.wTree.add_from_file(os.path.join(datadir, "offsetpage.glade"))
-        self.current_system = None
-        self.selection_mask = ()
-        self.axisletters = ["x", "y", "z", "a", "b", "c", "u", "v", "w"]
-
-        # global references
-        self.store = self.wTree.get_object("liststore2")
-        self.all_window = self.wTree.get_object("all_window")
-        self.view2 = self.wTree.get_object("treeview2")
-        self.view2.connect('button_press_event', self.on_treeview2_button_press_event)
-        self.selection = self.view2.get_selection()
-        self.selection.set_mode(gtk.SELECTION_SINGLE)
-        self.selection.connect("changed", self.on_selection_changed)
-        self.modelfilter = self.wTree.get_object("modelfilter")
-        self.edit_button = self.wTree.get_object("edit_button")
-        self.edit_button.connect('toggled', self.set_editing)
-        zero_g92_button = self.wTree.get_object("zero_g92_button")
-        zero_g92_button.connect('clicked', self.zero_g92)
-        zero_rot_button = self.wTree.get_object("zero_rot_button")
-        zero_rot_button.connect('clicked', self.zero_rot)
-        self.set_font(self.font)
-        self.modelfilter.set_visible_column(10)
-        self.buttonbox = self.wTree.get_object("buttonbox")
-        for col, name in enumerate(AXISLIST):
-            if col > 9:break
-            temp = self.wTree.get_object("cell_%s" % name)
-            temp.connect('edited', self.col_editted, col)
-        temp = self.wTree.get_object("cell_name")
-        temp.connect('edited', self.col_editted, 10)
-        # reparent offsetpage box from Glades top level window to widgets VBox
-        window = self.wTree.get_object("offsetpage_box")
-        window.reparent(self)
-
-        # check the ini file if UNITS are set to mm
-        # first check the global settings
-        # if not available then the X axis units
-        try:
-            self.inifile = self.linuxcnc.ini(INIPATH)
-            units = self.inifile.find("TRAJ", "LINEAR_UNITS")
-            if units == None:
-                units = self.inifile.find("AXIS_0", "UNITS")
-        except:
-            print "**** Offsetpage widget ERROR: LINEAR_UNITS not found in INI's TRAJ section"
-            units = "inch"
-
-        # now setup the conversion array depending on the machine native units
-        if units == "mm" or units == "metric" or units == "1.0":
-            self.machine_units_mm = 1
-            self.conversion = [1.0 / 25.4] * 3 + [1] * 3 + [1.0 / 25.4] * 3
-        else:
-            self.machine_units_mm = 0
-            self.conversion = [25.4] * 3 + [1] * 3 + [25.4] * 3
-
-        # check linuxcnc status every half second
-        gobject.timeout_add(500, self.periodic_check)
-
-    # Reload the offsets into display
-    def reload_offsets(self):
-        g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 = self.read_file()
-
-        # Get the offsets arrays and convert the units if the display
-        # is not in machine native units
-        g5x = self.status.g5x_offset
-        tool = self.status.tool_offset
-        g92 = self.status.g92_offset
-        rot = self.status.rotation_xy
-
-        if self.display_units_mm != self.machine_units_mm:
-            g5x = self.convert_units(g5x)
-            tool = self.convert_units(tool)
-            g92 = self.convert_units(g92)
-            g54 = self.convert_units(g54)
-            g55 = self.convert_units(g55)
-            g56 = self.convert_units(g56)
-            g57 = self.convert_units(g57)
-            g58 = self.convert_units(g58)
-            g59 = self.convert_units(g59)
-            g59_1 = self.convert_units(g59_1)
-            g59_2 = self.convert_units(g59_2)
-            g59_3 = self.convert_units(g59_3)
-
-        # set the text style based on unit type
-        if self.display_units_mm:
-            tmpl = self.mm_text_template
-        else:
-            tmpl = self.imperial_text_template
-
-        degree_tmpl = "%11.2f"
-
-        # fill each row of the liststore fron the offsets arrays
-        for row, i in enumerate([tool, g5x, rot, g92, g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3]):
-            for column in range(0, 9):
-                if row == 2:
-                    if column == 2:
-                        self.store[row][column + 1] = locale.format(degree_tmpl, rot)
-                    else:
-                        self.store[row][column + 1] = " "
-                else:
-                    self.store[row][column + 1] = locale.format(tmpl, i[column])
-            # set the current system's label's color - to make it stand out a bit
-            if self.store[row][0] == self.current_system:
-                self.store[row][13] = self.foreground_color
-            else:
-                self.store[row][13] = None
-            # mark unselectable rows a dirrerent color
-            if self.store[row][0] in self.selection_mask:
-                self.store[row][12] = self.unselectable_color
-
-    # This is for adding a filename path after the offsetpage is already loaded.
-    def set_filename(self, filename):
-        self.filename = filename
-        self.reload_offsets()
-
-    # We read the var file directly
-    # and pull out the info we need
-    # if anything goes wrong we set all the info to 0
-    def read_file(self):
-        g54 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g55 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g56 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g57 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g58 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g59 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g59_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g59_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        g59_3 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-        if self.filename == None:
-            return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3
-        if not os.path.exists(self.filename):
-            return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3
-        logfile = open(self.filename, "r").readlines()
-        for line in logfile:
-            temp = line.split()
-            param = int(temp[0])
-            data = float(temp[1])
-
-            if 5229 >= param >= 5221:
-                g54[param - 5221] = data
-            elif 5249 >= param >= 5241:
-                g55[param - 5241] = data
-            elif 5269 >= param >= 5261:
-                g56[param - 5261] = data
-            elif 5289 >= param >= 5281:
-                g57[param - 5281] = data
-            elif 5309 >= param >= 5301:
-                g58[param - 5301] = data
-            elif 5329 >= param >= 5321:
-                g59[param - 5321] = data
-            elif 5349 >= param >= 5341:
-                g59_1[param - 5341] = data
-            elif 5369 >= param >= 5361:
-                g59_2[param - 5361] = data
-            elif 5389 >= param >= 5381:
-                g59_3[param - 5381] = data
-        return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3
-
-    # This allows hiding or showing columns from a text string of columnns
-    # eg list ='ab'
-    # default, all the columns are shown
-    def set_col_visible(self, list, bool):
-        try:
-            for index in range(0, len(list)):
-                colstr = str(list[index])
-                colnum = "xyzabcuvwt".index(colstr.lower())
-                name = AXISLIST[colnum + 1]
-                renderer = self.wTree.get_object(name)
-                renderer.set_property('visible', bool)
-        except:
-            pass
-
-    # hide/show the offset rows from a text string of row ids
-    # eg list ='123'
-    def set_row_visible(self, list, bool):
-        try:
-            for index in range(0, len(list)):
-                rowstr = str(list[index])
-                rownum = "0123456789abcd".index(rowstr.lower())
-                self.store[rownum][10] = bool
-        except:
-            pass
-
-    # This does the units conversion
-    # it just multiplies the two arrays
-    def convert_units(self, v):
-        c = self.conversion
-        return map(lambda x, y: x * y, v, c)
-
-    # make the cells editable and highlight them
-    def set_editing(self, widget):
-        state = widget.get_active()
-        # stop updates from linuxcnc
-        self.editing_mode = state
-        # highlight editable rows
-        if state:
-            color = self.highlight_color
-        else:
-            color = None
-        # Set rows editable
-        for i in range(1, 13):
-            if not self.store[i][0] in('G5x', 'Rot', 'G92', 'G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1', 'G59.2', 'G59.3'): continue
-            if self.store[i][0] in self.selection_mask: continue
-            self.store[i][11] = state
-            self.store[i][12] = color
-        self.queue_draw()
-
-    # When the column is edited this does the work
-    # TODO the edited column does not end up showing the editted number even though linuxcnc
-    # registered the change
-    def col_editted(self, widget, filtered_path, new_text, col):
-        (store_path,) = self.modelfilter.convert_path_to_child_path(filtered_path)
-        row = store_path
-        axisnum = col - 1
-        # print "EDITED:", new_text, col, int(filtered_path), row, "axis num:", axisnum
-
-        def system_to_p(system):
-            convert = { "G54":1, "G55":2, "G56":3, "G57":4, "G58":5, "G59":6, "G59.1":7, "G59.2":8, "G59.3":9}
-            try:
-                pnum = convert[system]
-            except:
-                pnum = None
-            return pnum
-
-        # Hack to not edit any rotational offset but Z axis
-        if row == 2 and not col == 3: return
-
-        # set the text style based on unit type
-        if self.display_units_mm:
-            tmpl = lambda s: self.mm_text_template % s
-        else:
-            tmpl = lambda s: self.imperial_text_template % s
-
-        # allow 'name' columnn text to be arbitrarily changed
-        if col == 10:
-            self.store[row][14] = new_text
-            return
-        # set the text in the table
-        try:
-            self.store[row][col] = locale.format("%10.4f", locale.atof(new_text))
-        except:
-            print "offsetpage widget error: unrecognized float input"
-        # make sure we switch to correct units for machine and rotational, row 2, does not get converted
-        try:
-            if not self.display_units_mm == self.program_units and not row == 2:
-                if self.program_units == 1:
-                    convert = 25.4
-                else:
-                    convert = 1.0 / 25.4
-                qualified = float(locale.atof(new_text)) * convert
-            else:
-                qualified = float(locale.atof(new_text))
-        except:
-            print 'error'
-        # now update linuxcnc to the change
-        try:
-            global lncnc_runnning
-            if lncnc_running:
-                if self.status.task_mode != self.linuxcnc.MODE_MDI:
-                    self.cmd.mode(self.linuxcnc.MODE_MDI)
-                    self.cmd.wait_complete()
-                if row == 1:
-                    self.cmd.mdi("G10 L2 P0 %s %10.4f" % (self.axisletters[axisnum], qualified))
-                elif row == 2:
-                    if col == 3:
-                        self.cmd.mdi("G10 L2 P0 R %10.4f" % (qualified))
-                elif row == 3:
-                    self.cmd.mdi("G92 %s %10.4f" % (self.axisletters[axisnum], qualified))
-                else:
-                    pnum = system_to_p(self.store[row][0])
-                    if not pnum == None:
-                        self.cmd.mdi("G10 L2 P%d %s %10.4f" % (pnum, self.axisletters[axisnum], qualified))
-                self.cmd.mode(self.linuxcnc.MODE_MANUAL)
-                self.cmd.wait_complete()
-                self.cmd.mode(self.linuxcnc.MODE_MDI)
-                self.cmd.wait_complete()
-                self.gstat.emit('reload-display')
-        except:
-            print "offsetpage widget error: MDI call error"
-            self.reload_offsets()
-
-
-    # callback to cancel G92 when button pressed
-    def zero_g92(self, widget):
-        # print "zero g92"
-        if lncnc_running:
-            try:
-                if self.status.task_mode != self.linuxcnc.MODE_MDI:
-                    self.cmd.mode(self.linuxcnc.MODE_MDI)
-                    self.cmd.wait_complete()
-                self.cmd.mdi("G92.1")
-                self.cmd.mode(self.linuxcnc.MODE_MANUAL)
-                self.cmd.wait_complete()
-                self.cmd.mode(self.linuxcnc.MODE_MDI)
-                self.cmd.wait_complete()
-                self.gstat.emit('reload-display')
-            except:
-                print "MDI error in offsetpage widget -zero G92"
-
-    # callback to zero rotational offset when button pressed
-    def zero_rot(self, widget):
-        # print "zero rotation offset"
-        if lncnc_running:
-            try:
-                if self.status.task_mode != self.linuxcnc.MODE_MDI:
-                    self.cmd.mode(self.linuxcnc.MODE_MDI)
-                    self.cmd.wait_complete()
-                self.cmd.mdi("G10 L2 P0 R 0")
-                self.cmd.mode(self.linuxcnc.MODE_MANUAL)
-                self.cmd.wait_complete()
-                self.cmd.mode(self.linuxcnc.MODE_MDI)
-                self.cmd.wait_complete()
-                self.gstat.emit('reload-display')
-            except:
-                print "MDI error in offsetpage widget-zero rotational offset"
-
-    # check for linnuxcnc ON and IDLE which is the only safe time to edit the tool file.
-    # if in editing mode don't update else you can't actually edit
-    def periodic_check(self):
-        convert = ("None", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2", "G59.3")
-        try:
-            self.status.poll()
-            on = self.status.task_state > linuxcnc.STATE_OFF
-            idle = self.status.interp_state == linuxcnc.INTERP_IDLE
-            self.edit_button.set_sensitive(bool(on and idle))
-            self.current_system = convert[self.status.g5x_index]
-            self.program_units = int(self.status.program_units == 2)
-            if self.display_follows_program:
-                self.display_units_mm = self.program_units
-            global lncnc_running
-            lncnc_running = True
-        except:
-            self.current_system = "G54"
-            lncnc_running = False
-
-        if self.filename and not self.editing_mode:
-            self.reload_offsets()
-        return True
-
-    # sets the color when editing is active
-    def set_highlight_color(self, value):
-        self.highlight_color = gtk.gdk.Color(value)
-
-    # sets the text color of the current system description name
-    def set_foreground_color(self, value):
-        self.foreground_color = gtk.gdk.Color(value)
-
-    # Allows you to set the text font of all the rows and columns
-    def set_font(self, value):
-        for col, name in enumerate(AXISLIST):
-            if col > 10:break
-            temp = self.wTree.get_object("cell_" + name)
-            temp.set_property('font', value)
-
-    # helper function to set the units to inch
-    def set_to_inch(self):
-        self.display_units_mm = 0
-
-    # helper function to set the units to mm
-    def set_to_mm(self):
-        self.display_units_mm = 1
-
-    def set_display_follows_program_units(self):
-        self.display_follows_program = True
-
-    def set_display_independent_units(self):
-        self.display_follows_program = False
-
-    # helper function to hide control buttons
-    def hide_buttonbox(self, state):
-        if state:
-            self.buttonbox.hide()
-        else:
-            self.buttonbox.show()
-
-    # Mark the active system with cursor highlight
-    def mark_active(self, system):
-        try:
-            pathlist = []
-            for row in self.modelfilter:
-                if row[0] == system:
-                    pathlist.append(row.path)
-            if len(pathlist) == 1:
-                self.selection.select_path(pathlist[0])
-        except:
-            print "offsetpage_widget error: cannot select coordinate system", system
-
-    # Get the selected row the user clicked
-    def get_selected(self):
-        model, iter = self.selection.get_selected()
-        if iter:
-            system = model.get_value(iter, 0)
-            name = model.get_value(iter, 14)
-            # print "System:%s Name:%s"% (system,name)
-            return system, name
-        else:
-            return None, None
-
-    def on_selection_changed(self, treeselection):
-        system, name = self.get_selected()
-        # print self.status.g5x_index
-        if system in self.selection_mask:
-            self.mark_active(self.current_system)
-        self.emit("selection_changed", system, name)
-
-    def set_names(self, names):
-        for offset, name in names:
-            for row in range(0, 13):
-                if offset == self.store[row][0]:
-                    self.store[row][14] = name
-
-    def get_names(self):
-        temp = []
-        for row in range(0, 13):
-            temp.append([self.store[row][0], self.store[row][14]])
-        return temp
-
-    # For single click selection when in edit mode
-    def on_treeview2_button_press_event(self, widget, event):
-        if event.button == 1 : # left click
-            try:
-                path, model, x, y = widget.get_path_at_pos(int(event.x), int(event.y))
-                self.view2.set_cursor(path, None, True)
-            except:
-                pass
-
-    # standard Gobject method
-    def do_get_property(self, property):
-        name = property.name.replace('-', '_')
-        if name in self.__gproperties.keys():
-            return getattr(self, name)
-        else:
-            raise AttributeError('unknown property %s' % property.name)
-
-    # standard Gobject method
-    # This is so that in the Glade editor, you can change the display
-    def do_set_property(self, property, value):
-        name = property.name.replace('-', '_')
-        if name == 'font':
-            try:
-                self.set_font(value)
-            except:
-                pass
-        if name == 'hide_columns':
-            self.set_col_visible("xyzabcuvwt", True)
-            self.set_col_visible("%s" % value, False)
-        if name == 'hide_rows':
-            self.set_row_visible("0123456789abc", True)
-            self.set_row_visible("%s" % value, False)
-        if name in self.__gproperties.keys():
-            setattr(self, name, value)
-
-    # boiler code for variable access
-    def __getitem__(self, item):
-        return getattr(self, item)
-    def __setitem__(self, item, value):
-        return setattr(self, item, value)
-
-
-# for testing without glade editor:
-# Must linuxcnc running to see anything
-def main(filename = None):
-    window = gtk.Dialog("My dialog",
-                   None,
-                   gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                   (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
-                    gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
-    offsetpage = OffsetPage()
-
-    window.vbox.add(offsetpage)
-    # offsetpage.set_filename("../../../configs/sim/gscreen_custom/sim.var")
-    # offsetpage.set_col_visible("Yabuvw", False)
-    # offsetpage.set_row_visible("456789abc", False)
-    # offsetpage.set_row_visible("89abc", True)
-    # offsetpage.set_to_mm()
-    # offsetpage.set_font("sans 20")
-    # offsetpage.set_property("highlight_color", gtk.gdk.Color('blue'))
-    # offsetpage.set_highlight_color("violet")
-    # offsetpage.set_foreground_color("yellow")
-    # offsetpage.mark_active("G55")
-    # offsetpage.selection_mask = ("Tool", "Rot", "G5x")
-    # offsetpage.set_names([['G54', 'Default'], ["G55", "Vice1"], ['Rot', 'Rotational']])
-    # print offsetpage.get_names()
-
-    window.connect("destroy", gtk.main_quit)
-    window.show_all()
-    response = window.run()
-    if response == gtk.RESPONSE_ACCEPT:
-       print "True"
-    else:
-       print "False"
-
-if __name__ == "__main__":
-    main()
-
-
+#!/usr/bin/env python
+# GladeVcp Widget - offsetpage
+#
+# Copyright (c) 2013 Chris Morley
+#
+# 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.
+
+# This widget reads the offsets for current tool, current G5x, G92 using python library linuxcnc.
+# all other offsets are read directly from the Var file, if available, as linuxcnc does not give
+# access to all offsets thru NML, only current ones.
+# you can hide any axes or any columns
+# set metric or imperial
+# set the var file to search
+# set the text formatting for metric/imperial separately
+
+import sys, os, pango, linuxcnc
+from hal_glib import GStat
+datadir = os.path.abspath(os.path.dirname(__file__))
+AXISLIST = ['offset', 'X', 'Y', 'Z', 'A', 'B', 'C', 'U', 'V', 'W', 'name']
+# we need to know if linuxcnc isn't running when using the GLADE editor
+# as it causes big delays in response
+lncnc_running = False
+try:
+    import gobject, gtk
+except:
+    print('GTK not available')
+    sys.exit(1)
+
+# localization
+import locale
+BASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ".."))
+LOCALEDIR = os.path.join(BASE, "share", "locale")
+locale.setlocale(locale.LC_ALL, '')
+
+# we put this in a try so there is no error in the glade editor
+# linuxcnc is probably not running then
+try:
+    INIPATH = os.environ['INI_FILE_NAME']
+except:
+    pass
+
+class OffsetPage(gtk.VBox):
+    __gtype_name__ = 'OffsetPage'
+    __gproperties__ = {
+        'display_units_mm' : (gobject.TYPE_BOOLEAN, 'Display Units', 'Display in metric or not',
+                    False, gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
+        'mm_text_template' : (gobject.TYPE_STRING, 'Text template for Metric Units',
+                'Text template to display. Python formatting may be used for one variable',
+                "%10.3f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
+        'imperial_text_template' : (gobject.TYPE_STRING, 'Text template for Imperial Units',
+                'Text template to display. Python formatting may be used for one variable',
+                "%9.4f", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
+        'font' : (gobject.TYPE_STRING, 'Pango Font', 'Display font to use',
+                "sans 12", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
+        'highlight_color'  : (gtk.gdk.Color.__gtype__, 'Highlight color', "",
+                    gobject.PARAM_READWRITE),
+        'foreground_color'  : (gtk.gdk.Color.__gtype__, 'Active text color', "",
+                    gobject.PARAM_READWRITE),
+        'hide_columns' : (gobject.TYPE_STRING, 'Hidden Columns', 'A no-spaces list of axes to hide: xyzabcuvw and t are the options',
+                    "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
+        'hide_rows' : (gobject.TYPE_STRING, 'Hidden Rows', 'A no-spaces list of rows to hide: 0123456789abc are the options' ,
+                    "", gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT),
+    }
+    __gproperties = __gproperties__
+
+    __gsignals__ = {
+                    'selection_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING,)),
+                   }
+
+
+    def __init__(self, filename = None, *a, **kw):
+        super(OffsetPage, self).__init__()
+        self.gstat = GStat()
+        self.filename = filename
+        self.linuxcnc = linuxcnc
+        self.status = linuxcnc.stat()
+        self.cmd = linuxcnc.command()
+        self.hash_check = None
+        self.display_units_mm = 0 # imperial
+        self.machine_units_mm = 0 # imperial
+        self.program_units = 0 # imperial
+        self.display_follows_program = False # display units are chosen indepenadently of G20/G21
+        self.font = "sans 12"
+        self.editing_mode = False
+        self.highlight_color = gtk.gdk.Color("lightblue")
+        self.foreground_color = gtk.gdk.Color("red")
+        self.unselectable_color = gtk.gdk.Color("lightgray")
+        self.hidejointslist = []
+        self.hidecollist = []
+        self.wTree = gtk.Builder()
+        self.wTree.set_translation_domain("linuxcnc") # for locale translations
+        self.wTree.add_from_file(os.path.join(datadir, "offsetpage.glade"))
+        self.current_system = None
+        self.selection_mask = ()
+        self.axisletters = ["x", "y", "z", "a", "b", "c", "u", "v", "w"]
+
+        # global references
+        self.store = self.wTree.get_object("liststore2")
+        self.all_window = self.wTree.get_object("all_window")
+        self.view2 = self.wTree.get_object("treeview2")
+        self.view2.connect('button_press_event', self.on_treeview2_button_press_event)
+        self.selection = self.view2.get_selection()
+        self.selection.set_mode(gtk.SELECTION_SINGLE)
+        self.selection.connect("changed", self.on_selection_changed)
+        self.modelfilter = self.wTree.get_object("modelfilter")
+        self.edit_button = self.wTree.get_object("edit_button")
+        self.edit_button.connect('toggled', self.set_editing)
+        zero_g92_button = self.wTree.get_object("zero_g92_button")
+        zero_g92_button.connect('clicked', self.zero_g92)
+        zero_rot_button = self.wTree.get_object("zero_rot_button")
+        zero_rot_button.connect('clicked', self.zero_rot)
+        self.set_font(self.font)
+        self.modelfilter.set_visible_column(10)
+        self.buttonbox = self.wTree.get_object("buttonbox")
+        for col, name in enumerate(AXISLIST):
+            if col > 9:break
+            temp = self.wTree.get_object("cell_%s" % name)
+            temp.connect('edited', self.col_editted, col)
+        temp = self.wTree.get_object("cell_name")
+        temp.connect('edited', self.col_editted, 10)
+        # reparent offsetpage box from Glades top level window to widgets VBox
+        window = self.wTree.get_object("offsetpage_box")
+        window.reparent(self)
+
+        # check the ini file if UNITS are set to mm
+        # first check the global settings
+        # if not available then the X axis units
+        try:
+            self.inifile = self.linuxcnc.ini(INIPATH)
+            units = self.inifile.find("TRAJ", "LINEAR_UNITS")
+            if units == None:
+                units = self.inifile.find("AXIS_0", "UNITS")
+        except:
+            print "**** Offsetpage widget ERROR: LINEAR_UNITS not found in INI's TRAJ section"
+            units = "inch"
+
+        # now setup the conversion array depending on the machine native units
+        if units == "mm" or units == "metric" or units == "1.0":
+            self.machine_units_mm = 1
+            self.conversion = [1.0 / 25.4] * 3 + [1] * 3 + [1.0 / 25.4] * 3
+        else:
+            self.machine_units_mm = 0
+            self.conversion = [25.4] * 3 + [1] * 3 + [25.4] * 3
+
+        # check linuxcnc status every half second
+        gobject.timeout_add(500, self.periodic_check)
+
+    # Reload the offsets into display
+    def reload_offsets(self):
+        g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3 = self.read_file()
+
+        # Get the offsets arrays and convert the units if the display
+        # is not in machine native units
+        g5x = self.status.g5x_offset
+        tool = self.status.tool_offset
+        g92 = self.status.g92_offset
+        rot = self.status.rotation_xy
+
+        if self.display_units_mm != self.machine_units_mm:
+            g5x = self.convert_units(g5x)
+            tool = self.convert_units(tool)
+            g92 = self.convert_units(g92)
+            g54 = self.convert_units(g54)
+            g55 = self.convert_units(g55)
+            g56 = self.convert_units(g56)
+            g57 = self.convert_units(g57)
+            g58 = self.convert_units(g58)
+            g59 = self.convert_units(g59)
+            g59_1 = self.convert_units(g59_1)
+            g59_2 = self.convert_units(g59_2)
+            g59_3 = self.convert_units(g59_3)
+
+        # set the text style based on unit type
+        if self.display_units_mm:
+            tmpl = self.mm_text_template
+        else:
+            tmpl = self.imperial_text_template
+
+        degree_tmpl = "%11.2f"
+
+        # fill each row of the liststore fron the offsets arrays
+        for row, i in enumerate([tool, g5x, rot, g92, g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3]):
+            for column in range(0, 9):
+                if row == 2:
+                    if column == 2:
+                        self.store[row][column + 1] = locale.format(degree_tmpl, rot)
+                    else:
+                        self.store[row][column + 1] = " "
+                else:
+                    self.store[row][column + 1] = locale.format(tmpl, i[column])
+            # set the current system's label's color - to make it stand out a bit
+            if self.store[row][0] == self.current_system:
+                self.store[row][13] = self.foreground_color
+            else:
+                self.store[row][13] = None
+            # mark unselectable rows a dirrerent color
+            if self.store[row][0] in self.selection_mask:
+                self.store[row][12] = self.unselectable_color
+
+    # This is for adding a filename path after the offsetpage is already loaded.
+    def set_filename(self, filename):
+        self.filename = filename
+        self.reload_offsets()
+
+    # We read the var file directly
+    # and pull out the info we need
+    # if anything goes wrong we set all the info to 0
+    def read_file(self):
+        g54 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g55 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g56 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g57 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g58 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g59 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g59_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g59_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        g59_3 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        if self.filename == None:
+            return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3
+        if not os.path.exists(self.filename):
+            return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3
+        logfile = open(self.filename, "r").readlines()
+        for line in logfile:
+            temp = line.split()
+            param = int(temp[0])
+            data = float(temp[1])
+
+            if 5229 >= param >= 5221:
+                g54[param - 5221] = data
+            elif 5249 >= param >= 5241:
+                g55[param - 5241] = data
+            elif 5269 >= param >= 5261:
+                g56[param - 5261] = data
+            elif 5289 >= param >= 5281:
+                g57[param - 5281] = data
+            elif 5309 >= param >= 5301:
+                g58[param - 5301] = data
+            elif 5329 >= param >= 5321:
+                g59[param - 5321] = data
+            elif 5349 >= param >= 5341:
+                g59_1[param - 5341] = data
+            elif 5369 >= param >= 5361:
+                g59_2[param - 5361] = data
+            elif 5389 >= param >= 5381:
+                g59_3[param - 5381] = data
+        return g54, g55, g56, g57, g58, g59, g59_1, g59_2, g59_3
+
+    # This allows hiding or showing columns from a text string of columnns
+    # eg list ='ab'
+    # default, all the columns are shown
+    def set_col_visible(self, list, bool):
+        try:
+            for index in range(0, len(list)):
+                colstr = str(list[index])
+                colnum = "xyzabcuvwt".index(colstr.lower())
+                name = AXISLIST[colnum + 1]
+                renderer = self.wTree.get_object(name)
+                renderer.set_property('visible', bool)
+        except:
+            pass
+
+    # hide/show the offset rows from a text string of row ids
+    # eg list ='123'
+    def set_row_visible(self, list, bool):
+        try:
+            for index in range(0, len(list)):
+                rowstr = str(list[index])
+                rownum = "0123456789abcd".index(rowstr.lower())
+                self.store[rownum][10] = bool
+        except:
+            pass
+
+    # This does the units conversion
+    # it just multiplies the two arrays
+    def convert_units(self, v):
+        c = self.conversion
+        return map(lambda x, y: x * y, v, c)
+
+    # make the cells editable and highlight them
+    def set_editing(self, widget):
+        state = widget.get_active()
+        # stop updates from linuxcnc
+        self.editing_mode = state
+        # highlight editable rows
+        if state:
+            color = self.highlight_color
+        else:
+            color = None
+        # Set rows editable
+        for i in range(1, 13):
+            if not self.store[i][0] in('G5x', 'Rot', 'G92', 'G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1', 'G59.2', 'G59.3'): continue
+            if self.store[i][0] in self.selection_mask: continue
+            self.store[i][11] = state
+            self.store[i][12] = color
+        self.queue_draw()
+
+    # When the column is edited this does the work
+    # TODO the edited column does not end up showing the editted number even though linuxcnc
+    # registered the change
+    def col_editted(self, widget, filtered_path, new_text, col):
+        (store_path,) = self.modelfilter.convert_path_to_child_path(filtered_path)
+        row = store_path
+        axisnum = col - 1
+        # print "EDITED:", new_text, col, int(filtered_path), row, "axis num:", axisnum
+
+        def system_to_p(system):
+            convert = { "G54":1, "G55":2, "G56":3, "G57":4, "G58":5, "G59":6, "G59.1":7, "G59.2":8, "G59.3":9}
+            try:
+                pnum = convert[system]
+            except:
+                pnum = None
+            return pnum
+
+        # Hack to not edit any rotational offset but Z axis
+        if row == 2 and not col == 3: return
+
+        # set the text style based on unit type
+        if self.display_units_mm:
+            tmpl = lambda s: self.mm_text_template % s
+        else:
+            tmpl = lambda s: self.imperial_text_template % s
+
+        # allow 'name' columnn text to be arbitrarily changed
+        if col == 10:
+            self.store[row][14] = new_text
+            return
+        # set the text in the table
+        try:
+            self.store[row][col] = locale.format("%10.4f", locale.atof(new_text))
+        except:
+            print "offsetpage widget error: unrecognized float input"
+        # make sure we switch to correct units for machine and rotational, row 2, does not get converted
+        try:
+            if not self.display_units_mm == self.program_units and not row == 2:
+                if self.program_units == 1:
+                    convert = 25.4
+                else:
+                    convert = 1.0 / 25.4
+                qualified = float(locale.atof(new_text)) * convert
+            else:
+                qualified = float(locale.atof(new_text))
+        except:
+            print 'error'
+        # now update linuxcnc to the change
+        try:
+            global lncnc_runnning
+            if lncnc_running:
+                if self.status.task_mode != self.linuxcnc.MODE_MDI:
+                    self.cmd.mode(self.linuxcnc.MODE_MDI)
+                    self.cmd.wait_complete()
+                if row == 1:
+                    self.cmd.mdi("G10 L2 P0 %s %10.4f" % (self.axisletters[axisnum], qualified))
+                elif row == 2:
+                    if col == 3:
+                        self.cmd.mdi("G10 L2 P0 R %10.4f" % (qualified))
+                elif row == 3:
+                    self.cmd.mdi("G92 %s %10.4f" % (self.axisletters[axisnum], qualified))
+                else:
+                    pnum = system_to_p(self.store[row][0])
+                    if not pnum == None:
+                        self.cmd.mdi("G10 L2 P%d %s %10.4f" % (pnum, self.axisletters[axisnum], qualified))
+                self.cmd.mode(self.linuxcnc.MODE_MANUAL)
+                self.cmd.wait_complete()
+                self.cmd.mode(self.linuxcnc.MODE_MDI)
+                self.cmd.wait_complete()
+                self.gstat.emit('reload-display')
+        except:
+            print "offsetpage widget error: MDI call error"
+            self.reload_offsets()
+
+
+    # callback to cancel G92 when button pressed
+    def zero_g92(self, widget):
+        # print "zero g92"
+        if lncnc_running:
+            try:
+                if self.status.task_mode != self.linuxcnc.MODE_MDI:
+                    self.cmd.mode(self.linuxcnc.MODE_MDI)
+                    self.cmd.wait_complete()
+                self.cmd.mdi("G92.1")
+                self.cmd.mode(self.linuxcnc.MODE_MANUAL)
+                self.cmd.wait_complete()
+                self.cmd.mode(self.linuxcnc.MODE_MDI)
+                self.cmd.wait_complete()
+                self.gstat.emit('reload-display')
+            except:
+                print "MDI error in offsetpage widget -zero G92"
+
+    # callback to zero rotational offset when button pressed
+    def zero_rot(self, widget):
+        # print "zero rotation offset"
+        if lncnc_running:
+            try:
+                if self.status.task_mode != self.linuxcnc.MODE_MDI:
+                    self.cmd.mode(self.linuxcnc.MODE_MDI)
+                    self.cmd.wait_complete()
+                self.cmd.mdi("G10 L2 P0 R 0")
+                self.cmd.mode(self.linuxcnc.MODE_MANUAL)
+                self.cmd.wait_complete()
+                self.cmd.mode(self.linuxcnc.MODE_MDI)
+                self.cmd.wait_complete()
+                self.gstat.emit('reload-display')
+            except:
+                print "MDI error in offsetpage widget-zero rotational offset"
+
+    # check for linnuxcnc ON and IDLE which is the only safe time to edit the tool file.
+    # if in editing mode don't update else you can't actually edit
+    def periodic_check(self):
+        convert = ("None", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2", "G59.3")
+        try:
+            self.status.poll()
+            on = self.status.task_state > linuxcnc.STATE_OFF
+            idle = self.status.interp_state == linuxcnc.INTERP_IDLE
+            self.edit_button.set_sensitive(bool(on and idle))
+            self.current_system = convert[self.status.g5x_index]
+            self.program_units = int(self.status.program_units == 2)
+            if self.display_follows_program:
+                self.display_units_mm = self.program_units
+            global lncnc_running
+            lncnc_running = True
+        except:
+            self.current_system = "G54"
+            lncnc_running = False
+
+        if self.filename and not self.editing_mode:
+            self.reload_offsets()
+        return True
+
+    # sets the color when editing is active
+    def set_highlight_color(self, value):
+        self.highlight_color = gtk.gdk.Color(value)
+
+    # sets the text color of the current system description name
+    def set_foreground_color(self, value):
+        self.foreground_color = gtk.gdk.Color(value)
+
+    # Allows you to set the text font of all the rows and columns
+    def set_font(self, value):
+        for col, name in enumerate(AXISLIST):
+            if col > 10:break
+            temp = self.wTree.get_object("cell_" + name)
+            temp.set_property('font', value)
+
+    # helper function to set the units to inch
+    def set_to_inch(self):
+        self.display_units_mm = 0
+
+    # helper function to set the units to mm
+    def set_to_mm(self):
+        self.display_units_mm = 1
+
+    def set_display_follows_program_units(self):
+        self.display_follows_program = True
+
+    def set_display_independent_units(self):
+        self.display_follows_program = False
+
+    # helper function to hide control buttons
+    def hide_buttonbox(self, state):
+        if state:
+            self.buttonbox.hide()
+        else:
+            self.buttonbox.show()
+
+    # Mark the active system with cursor highlight
+    def mark_active(self, system):
+        try:
+            pathlist = []
+            for row in self.modelfilter:
+                if row[0] == system:
+                    pathlist.append(row.path)
+            if len(pathlist) == 1:
+                self.selection.select_path(pathlist[0])
+        except:
+            print "offsetpage_widget error: cannot select coordinate system", system
+
+    # Get the selected row the user clicked
+    def get_selected(self):
+        model, iter = self.selection.get_selected()
+        if iter:
+            system = model.get_value(iter, 0)
+            name = model.get_value(iter, 14)
+            # print "System:%s Name:%s"% (system,name)
+            return system, name
+        else:
+            return None, None
+
+    def on_selection_changed(self, treeselection):
+        system, name = self.get_selected()
+        # print self.status.g5x_index
+        if system in self.selection_mask:
+            self.mark_active(self.current_system)
+        self.emit("selection_changed", system, name)
+
+    def set_names(self, names):
+        for offset, name in names:
+            for row in range(0, 13):
+                if offset == self.store[row][0]:
+                    self.store[row][14] = name
+
+    def get_names(self):
+        temp = []
+        for row in range(0, 13):
+            temp.append([self.store[row][0], self.store[row][14]])
+        return temp
+
+    # For single click selection when in edit mode
+    def on_treeview2_button_press_event(self, widget, event):
+        if event.button == 1 : # left click
+            try:
+                path, model, x, y = widget.get_path_at_pos(int(event.x), int(event.y))
+                self.view2.set_cursor(path, None, True)
+            except:
+                pass
+
+    # standard Gobject method
+    def do_get_property(self, property):
+        name = property.name.replace('-', '_')
+        if name in self.__gproperties.keys():
+            return getattr(self, name)
+        else:
+            raise AttributeError('unknown property %s' % property.name)
+
+    # standard Gobject method
+    # This is so that in the Glade editor, you can change the display
+    def do_set_property(self, property, value):
+        name = property.name.replace('-', '_')
+        if name == 'font':
+            try:
+                self.set_font(value)
+            except:
+                pass
+        if name == 'hide_columns':
+            self.set_col_visible("xyzabcuvwt", True)
+            self.set_col_visible("%s" % value, False)
+        if name == 'hide_rows':
+            self.set_row_visible("0123456789abc", True)
+            self.set_row_visible("%s" % value, False)
+        if name in self.__gproperties.keys():
+            setattr(self, name, value)
+
+    # boiler code for variable access
+    def __getitem__(self, item):
+        return getattr(self, item)
+    def __setitem__(self, item, value):
+        return setattr(self, item, value)
+
+
+# for testing without glade editor:
+# Must linuxcnc running to see anything
+def main(filename = None):
+    window = gtk.Dialog("My dialog",
+                   None,
+                   gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+                   (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
+                    gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+    offsetpage = OffsetPage()
+
+    window.vbox.add(offsetpage)
+    # offsetpage.set_filename("../../../configs/sim/gscreen_custom/sim.var")
+    # offsetpage.set_col_visible("Yabuvw", False)
+    # offsetpage.set_row_visible("456789abc", False)
+    # offsetpage.set_row_visible("89abc", True)
+    # offsetpage.set_to_mm()
+    # offsetpage.set_font("sans 20")
+    # offsetpage.set_property("highlight_color", gtk.gdk.Color('blue'))
+    # offsetpage.set_highlight_color("violet")
+    # offsetpage.set_foreground_color("yellow")
+    # offsetpage.mark_active("G55")
+    # offsetpage.selection_mask = ("Tool", "Rot", "G5x")
+    # offsetpage.set_names([['G54', 'Default'], ["G55", "Vice1"], ['Rot', 'Rotational']])
+    # print offsetpage.get_names()
+
+    window.connect("destroy", gtk.main_quit)
+    window.show_all()
+    response = window.run()
+    if response == gtk.RESPONSE_ACCEPT:
+       print "True"
+    else:
+       print "False"
+
+if __name__ == "__main__":
+    main()
+
+
-- 
cgit v1.2.3