def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.current_mode = (None, None)
     self._last_count = 0
     self.STYLEEDITOR = SSE(widgets, paths)
Esempio n. 2
0
 def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.PATH = paths.CONFIGPATH
     self.IMAGE_PATH = paths.IMAGEDIR
     self._big_view = -1
     self.STYLEEDITOR = SSE(widgets, paths)
Esempio n. 3
0
 def __init__(self, halcomp,widgets,paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.STYLEEDITOR = SSE(widgets,paths)
     self.picked_line = None
     STATUS.connect('general',self.return_value)
     STATUS.connect('graphics-line-selected', self.set_picked_line)
Esempio n. 4
0
 def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.STYLEEDITOR = SSE(widgets, paths)
     global TOOLBAR
     TOOLBAR = ToolBarActions(path=paths)
     STATUS.connect('general', self.return_value)
Esempio n. 5
0
 def __init__(self, halcomp,widgets,paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.STYLEEDITOR = SSE(widgets,paths)
     self.picked_line = None
     STATUS.connect('general',self.return_value)
     STATUS.connect('graphics-line-selected', self.set_picked_line)
Esempio n. 6
0
 def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.STYLEEDITOR = SSE(widgets, paths)
     global TOOLBAR
     STATUS.connect('general', self.return_value)
     STATUS.connect('motion-mode-changed', self.motion_mode)
     STATUS.connect('user-system-changed', self._set_user_system_text)
     STATUS.connect('actual-spindle-speed-changed', self.update_spindle)
Esempio n. 7
0
 def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.STYLEEDITOR = SSE(widgets, paths)
     global TOOLBAR
     TOOLBAR = ToolBarActions(path=paths)
     STATUS.connect('general', self.return_value)
     STATUS.connect('motion-mode-changed', self.motion_mode)
     STATUS.connect('user-system-changed', self._set_user_system_text)
Esempio n. 8
0
 def __init__(self, halcomp,widgets,paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.STYLEEDITOR = SSE(widgets,paths)
     global TOOLBAR
     TOOLBAR = ToolBarActions(path=paths)
     STATUS.connect('general',self.return_value)
     STATUS.connect('motion-mode-changed',self.motion_mode)
     STATUS.connect('user-system-changed', self._set_user_system_text)
Esempio n. 9
0
 def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.stat = linuxcnc.stat()
     self.cmnd = linuxcnc.command()
     self.error = linuxcnc.error_channel()
     self.PATHS = paths
     self.IMAGE_PATH = paths.IMAGEDIR
     self.STYLEEDITOR = SSE(widgets, paths)
     global TOOLBAR
     TOOLBAR = ToolBarActions(path=paths)
Esempio n. 10
0
    def __init__(self, halcomp, widgets, paths):
        self.h = halcomp
        self.w = widgets
        self.gcodes = GCodes(widgets)
        self.valid = QtGui.QDoubleValidator(-999.999, 999.999, 3)
        self.styleeditor = SSE(widgets, paths)
        KEYBIND.add_call('Key_F4', 'on_keycall_F4')
        KEYBIND.add_call('Key_F12','on_keycall_F12')
        KEYBIND.add_call('Key_Pause', 'on_keycall_PAUSE')
        KEYBIND.add_call('Key_Space', 'on_keycall_PAUSE')
        # some global variables
        self.factor = 1.0
        self.probe = None
        self.default_setup = os.path.join(PATH.CONFIGPATH, "default_setup.html")
        self.start_line = 0
        self.run_time = 0
        self.time_tenths = 0
        self.timer_on = False
        self.home_all = False
        self.min_spindle_rpm = INFO.MIN_SPINDLE_SPEED
        self.max_spindle_rpm = INFO.MAX_SPINDLE_SPEED
        self.max_spindle_power = INFO.get_error_safe_setting('DISPLAY', 'MAX_SPINDLE_POWER',"0")
        self.max_linear_velocity = INFO.MAX_TRAJ_VELOCITY
        self.system_list = ["G54","G55","G56","G57","G58","G59","G59.1","G59.2","G59.3"]
        self.slow_jog_factor = 10
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.first_turnon = True
        self.unit_label_list = ["ts_height", "tp_height", "zoffset_units", "max_probe_units"]
        self.lineedit_list = ["work_height", "touch_height", "sensor_height", "laser_x", "laser_y",
                              "sensor_x", "sensor_y", "camera_x", "camera_y",
                              "search_vel", "probe_vel", "max_probe", "eoffset_count"]
        self.onoff_list = ["frame_program", "frame_tool", "frame_offsets", "frame_dro", "frame_override"]
        self.axis_a_list = ["label_axis_a", "dro_axis_a", "action_zero_a", "axistoolbutton_a",
                            "action_home_a", "widget_jog_angular", "widget_increments_angular",
                            "a_plus_jogbutton", "a_minus_jogbutton"]

        STATUS.connect('general', self.dialog_return)
        STATUS.connect('state-on', lambda w: self.enable_onoff(True))
        STATUS.connect('state-off', lambda w: self.enable_onoff(False))
        STATUS.connect('mode-auto', lambda w: self.enable_auto(True))
        STATUS.connect('gcode-line-selected', lambda w, line: self.set_start_line(line))
        STATUS.connect('hard-limits-tripped', self.hard_limit_tripped)
        STATUS.connect('program-pause-changed', lambda w, state: self.w.btn_pause_spindle.setEnabled(state))
        STATUS.connect('user-system-changed', lambda w, data: self.user_system_changed(data))
        STATUS.connect('metric-mode-changed', lambda w, mode: self.metric_mode_changed(mode))
        STATUS.connect('file-loaded', self.file_loaded)
        STATUS.connect('all-homed', self.all_homed)
        STATUS.connect('not-all-homed', self.not_all_homed)
        STATUS.connect('periodic', lambda w: self.update_runtimer())
        STATUS.connect('interp-idle', lambda w: self.stop_timer())
        STATUS.connect('actual-spindle-speed-changed',self.update_spindle)
        STATUS.connect('requested-spindle-speed-changed',self.update_spindle_requested)
Esempio n. 11
0
    def __init__(self, halcomp, widgets, paths):
        # some global variables
        self.hal = halcomp
        self.w = widgets
        self.PATH = paths
        self._big_view = -1
        self.flag = 0
        self.activeStyle = ''' { background-color: white;}'''
        self.defaultStyle = ''' { background-color: light blue;}'''
        self.activeWidgetDict = {
            'programPage': False,
            'userPage': False,
            'machinePage': False,
            'tooloffsetsPage': False,
            'loadPage': False,
            'mdiPage': False,
            'workoffsetsPage': False,
            'setupPage': False
        }
        self.current_mode = (None, None)
        self._last_count = 0
        self.run_time = 0
        self.time_tenths = 0
        self.timerOn = False
        self.slow_jog_factor = 10

        self.STYLEEDITOR = SSE(widgets, paths)
        self.GCODES = GCodes()

        STATUS.connect('periodic', lambda w: self.update_runtimer())
        STATUS.connect('command-running', lambda w: self.start_timer())
        STATUS.connect('command-stopped', lambda w: self.stop_timer())
        STATUS.connect("metric-mode-changed",
                       lambda w, d: self.mode_changed(d))
        STATUS.connect('state-off',
                       lambda w: self.w.pushbutton_metric.setEnabled(False))
        STATUS.connect('state-estop',
                       lambda w: self.w.pushbutton_metric.setEnabled(False))
        STATUS.connect(
            'interp-idle', lambda w: self.w.pushbutton_metric.setEnabled(
                self.homed_on_test()))
        STATUS.connect('interp-run',
                       lambda w: self.w.pushbutton_metric.setEnabled(False))
        STATUS.connect('all-homed',
                       lambda w: self.w.pushbutton_metric.setEnabled(True))
        STATUS.connect(
            'not-all-homed',
            lambda w, data: self.w.pushbutton_metric.setEnabled(False))
Esempio n. 12
0
    def __init__(self, halcomp, widgets, paths):
        self.h = halcomp
        self.w = widgets
        self.PATHS = paths
        INIPATH = os.environ.get('INI_FILE_NAME', '/dev/null')
        self.inifile = linuxcnc.ini(INIPATH)
        self.STYLEEDITOR = SSE(widgets, paths)
        self.GCODES = GCodes(widgets)
        self.valid = QtGui.QDoubleValidator(0.0, 999.999, 3)

        KEYBIND.add_call('Key_F12', 'on_keycall_F12')
        KEYBIND.add_call('Key_Pause', 'on_keycall_pause')
        KEYBIND.add_call('Key_Plus', 'on_keycall_plus')
        KEYBIND.add_call('Key_Minus', 'on_keycall_minus')

        STAT.connect('general', self.dialog_return)
        STAT.connect('state-on', lambda w: self.enable_onoff(True))
        STAT.connect('state-off', lambda w: self.enable_onoff(False))
        STAT.connect('gcode-line-selected',
                     lambda w, line: self.set_start_line(line))
        STAT.connect('hard-limits-tripped', self.hard_limit_tripped)
        STAT.connect('interp-idle', lambda w: self.set_start_line(0))
        STAT.connect('user-system-changed', self.user_system_changed)
        STAT.connect('file-loaded', self.file_loaded)
        STAT.connect('all-homed', self.all_homed)
        STAT.connect('not-all-homed',
                     lambda w, list: self.set_dro_homed(False))

        # some global variables
        self.axis_list = INFO.AVAILABLE_AXES
        self.max_linear_velocity = INFO.MAX_LINEAR_VELOCITY
        self.max_spindle_rpm = INFO.MAX_SPINDLE_SPEED
        self.system_list = [
            "G53", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2",
            "G59.3"
        ]
        self.slow_jog_factor = 10
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.first_turnon = True
        self.onoff_list = ["frame_program", "frame_tool", "frame_dro"]
        self.axis_a_list = [
            "label_axis_a", "dro_axis_a", "action_zero_a", "axistoolbutton_a",
            "action_home_a", "widget_jog_angular", "widget_increments_angular",
            "a_plus_jogbutton", "a_minus_jogbutton"
        ]
Esempio n. 13
0
    def __init__(self, halcomp, widgets, paths):
        self.w = widgets
        self.PATHS = paths
        self.hal = halcomp
        INIPATH = os.environ.get('INI_FILE_NAME', '/dev/null')
        self.inifile = linuxcnc.ini(INIPATH)
        self.STYLEEDITOR = SSE(widgets, paths)
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')

        #        STAT.connect('general',self.return_value)
        STAT.connect('state-on', self.machine_on)
        STAT.connect('state-off', self.machine_off)
        STAT.connect('gcode-line-selected', self.gcode_line_selected)
        STAT.connect('hard-limits-tripped', self.hard_limit_tripped)
        STAT.connect("interp-idle", self.interp_idle_changed)
        STAT.connect("user-system-changed", self.user_system_changed)
        STAT.connect("tool-in-spindle-changed", self.tool_in_spindle_changed)
        STAT.connect("file-loaded", self.file_loaded)
        STAT.connect("all-homed", self.all_homed)
        STAT.connect("not-all-homed", self.not_homed)

        # some global variables
        self.axis_list = INFO.AVAILABLE_AXES
        self.joint_list = INFO.AVAILABLE_JOINTS
        self.max_velocity = INFO.MAX_LINEAR_VELOCITY
        self.system_list = [
            "G53", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2",
            "G59.3"
        ]
        self.home_location_x = self.inifile.find('JOINT_0', 'HOME')
        self.home_location_y = self.inifile.find('JOINT_1', 'HOME')
        self.home_location_z = self.inifile.find('JOINT_2', 'HOME')
        self.tool_sensor_x = self.inifile.find('TOOLSENSOR', 'X')
        self.tool_sensor_y = self.inifile.find('TOOLSENSOR', 'Y')
        self.laser_offset_x = self.inifile.find('LASER', 'X')
        self.laser_offset_y = self.inifile.find('LASER', 'Y')
        self.homed = False
        self.start_line = 0
        self.program_length = 0
        self.slow_jog_factor = 10
        self.tool_in_spindle = 0
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.onoff_list = ["widget_controls", "Program_frame", "DRO_frame"]
Esempio n. 14
0
 def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.PATH = paths
     self._big_view = -1
     self.STYLEEDITOR = SSE(widgets, paths)
     self.flag = 0
     self.activeStyle = ''' { background-color: white;}'''
     self.defaultStyle = ''' { background-color: light blue;}'''
     self.activeWidgetDict = {
         'programPage': False,
         'userPage': False,
         'machinePage': False,
         'tooloffsetsPage': False,
         'loadPage': False,
         'mdiPage': False,
         'workoffsetsPage': False,
         'setupPage': False
     }
     self.current_mode = (None, None)
     self._last_count = 0
Esempio n. 15
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        self.hal = halcomp
        self.w = widgets
        self.PATHS = paths
        self.STYLEEDITOR = SSE(widgets, paths)
        global TOOLBAR
        TOOLBAR = ToolBarActions(path=paths)
        STATUS.connect('general', self.return_value)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')
        TOOLBAR.configure_submenu(self.w.menuRecent, 'recent_submenu')
        TOOLBAR.configure_submenu(self.w.menuHoming, 'home_submenu')
        TOOLBAR.configure_submenu(self.w.menuUnhome, 'unhome_submenu')
        TOOLBAR.configure_submenu(self.w.menuZeroCoordinateSystem,
                                  'zero_systems_submenu')
        TOOLBAR.configure_action(self.w.actionEstop, 'estop')
        TOOLBAR.configure_action(self.w.actionMachineOn, 'power')
        TOOLBAR.configure_action(self.w.actionOpen, 'load')
        TOOLBAR.configure_action(self.w.actionReload, 'Reload')
        TOOLBAR.configure_action(self.w.actionRun, 'run')
        TOOLBAR.configure_action(self.w.actionPause, 'pause')
        TOOLBAR.configure_action(self.w.actionStop, 'abort')
        TOOLBAR.configure_action(self.w.actionSkip, 'block_delete')
        TOOLBAR.configure_action(self.w.actionOptionalStop, 'optional_stop')
        TOOLBAR.configure_action(self.w.actionZoomIn, 'zoom_in')
        TOOLBAR.configure_action(self.w.actionZoomOut, 'zoom_out')
        TOOLBAR.configure_action(self.w.actionFrontView, 'view_x')
        TOOLBAR.configure_action(self.w.actionSideView, 'view_y')
        TOOLBAR.configure_action(self.w.actionRotatedView, 'view_z2')
        TOOLBAR.configure_action(self.w.actionTopView, 'view_z')
        TOOLBAR.configure_action(self.w.actionPerspectiveView, 'view_p')
        TOOLBAR.configure_action(self.w.actionClearPlot, 'view_clear')
        TOOLBAR.configure_action(self.w.actionQuit, 'Quit',
                                 lambda d: self.w.close())
        TOOLBAR.configure_action(self.w.actionProperties, 'gcode_properties')
        TOOLBAR.configure_action(self.w.actionCalibration, 'load_calibration')
        TOOLBAR.configure_action(self.w.actionStatus, 'load_status')
        TOOLBAR.configure_action(self.w.actionHalshow, 'load_halshow')
        TOOLBAR.configure_action(self.w.actionHalmeter, 'load_halmeter')
        TOOLBAR.configure_action(self.w.actionHalscope, 'load_halscope')
        TOOLBAR.configure_action(self.w.actionAbout, 'about')
        TOOLBAR.configure_action(self.w.actionTouchoffWorkplace,
                                 'touchoffworkplace')
        TOOLBAR.configure_action(self.w.actionEdit, 'edit', self.edit)
        TOOLBAR.configure_action(self.w.actionTouchoffFixture,
                                 'touchofffixture')
        TOOLBAR.configure_action(self.w.actionRunFromLine, 'runfromline')
        self.w.actionQuickRef.triggered.connect(self.quick_reference)

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = False
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    #######################
    # callbacks from form #
    #######################

    def tool_offset_clicked(self):
        conversion = {
            0: "X",
            1: "Y",
            2: "Z",
            3: "A",
            4: "B",
            5: "C",
            6: "U",
            7: "V",
            8: "W"
        }
        axis = STATUS.get_selected_axis()
        mess = {
            'NAME': 'ENTRY',
            'ID': 'FORM__',
            'AXIS': conversion[axis],
            'FIXTURE': self.w.actionTouchoffWorkplace.isChecked(),
            'TITLE': 'Set Tool Offset'
        }
        STATUS.emit('dialog-request', mess)
        LOG.debug('message sent:{}'.format(mess))

    #####################
    # general functions #
    #####################

    # process the STATUS return message
    def return_value(self, w, message):
        num = message['RETURN']
        code = bool(message['ID'] == 'FORM__')
        name = bool(message['NAME'] == 'ENTRY')
        if num and code and name:
            LOG.debug('message return:{}'.format(message))
            axis = message['AXIS']
            fixture = message['FIXTURE']
            ACTION.SET_TOOL_OFFSET(axis, num, fixture)
            STATUS.emit('update-machine-log',
                        'Set tool offset of Axis %s to %f' % (axis, num),
                        'TIME')

    def edit(self, widget, state):
        if state:
            self.w.gcode_editor.editMode()
        else:
            self.w.gcode_editor.readOnlyMode()

    def quick_reference(self):
        help1 = [
            ("F1", _("Emergency stop")),
            ("F2", _("Turn machine on")),
            ("", ""),
            ("X", _("Activate first axis")),
            ("Y", _("Activate second axis")),
            ("Z", _("Activate third axis")),
            ("A", _("Activate fourth axis")),
            ("` or 0,1..8",
             _("Activate first through ninth joint <br>if joints radiobuttons visible"
               )),
            ("", _("")),
            ("`,1..9,0", _("Set Feed Override from 0% to 100%")),
            ("", _("if axes radiobuttons visible")),
            (_(", and ."), _("Select jog speed")),
            (_("< and >"), _("Select angular jog speed")),
            (_("I, Shift-I"), _("Select jog increment")),
            ("C", _("Continuous jog")),
            (_("Home"), _("Send active joint home")),
            (_("Ctrl-Home"), _("Home all joints")),
            (_("Shift-Home"), _("Zero G54 offset for active axis")),
            (_("End"), _("Set G54 offset for active axis")),
            (_("Ctrl-End"), _("Set tool offset for loaded tool")),
            ("-, =", _("Jog active axis or joint")),
            (";, '", _("Select Max velocity")),
            ("", ""),
            (_("Left, Right"), _("Jog first axis or joint")),
            (_("Up, Down"), _("Jog second axis or joint")),
            (_("Pg Up, Pg Dn"), _("Jog third axis or joint")),
            (_("Shift+above jogs"), _("Jog at traverse speed")),
            ("[, ]", _("Jog fourth axis or joint")),
            ("", ""),
            ("D", _("Toggle between Drag and Rotate mode")),
            (_("Left Button"), _("Pan, rotate or select line")),
            (_("Shift+Left Button"), _("Rotate or pan")),
            (_("Right Button"), _("Zoom view")),
            (_("Wheel Button"), _("Rotate view")),
            (_("Rotate Wheel"), _("Zoom view")),
            (_("Control+Left Button"), _("Zoom view")),
        ]
        help2 = [
            ("F3", _("Manual control")),
            ("F5", _("Code entry (MDI)")),
            (_("Control-M"), _("Clear MDI history")),
            (_("Control-H"), _("Copy selected MDI history elements")),
            ("", _("to clipboard")),
            (_("Control-Shift-H"), _("Paste clipboard to MDI history")),
            ("L", _("Override Limits")),
            ("", ""),
            ("O", _("Open program")),
            (_("Control-R"), _("Reload program")),
            (_("Control-S"), _("Save g-code as")),
            ("R", _("Run program")),
            ("T", _("Step program")),
            ("P", _("Pause program")),
            ("S", _("Resume program")),
            ("ESC", _("Stop running program, or")),
            ("", _("stop loading program preview")),
            ("", ""),
            ("F7", _("Toggle mist")),
            ("F8", _("Toggle flood")),
            ("B", _("Spindle brake off")),
            (_("Shift-B"), _("Spindle brake on")),
            ("F9", _("Turn spindle clockwise")),
            ("F10", _("Turn spindle counterclockwise")),
            ("F11", _("Turn spindle more slowly")),
            ("F12", _("Turn spindle more quickly")),
            (_("Control-K"), _("Clear live plot")),
            ("V", _("Cycle among preset views")),
            ("F4", _("Cycle among preview, DRO, and user tabs")),
            ("@", _("toggle Actual/Commanded")),
            ("#", _("toggle Relative/Machine")),
            (_("Ctrl-Space"), _("Clear notifications")),
            (_("Alt-F, M, V"), _("Open a Menu")),
        ]
        help = zip(help1, help2)
        msg = QtWidgets.QDialog()
        msg.setWindowTitle("Quick Reference")
        button = QtWidgets.QPushButton("Ok")
        button.clicked.connect(lambda: msg.close())
        edit = QtWidgets.QTextEdit()
        edit.setLineWrapMode(0)

        mess = '''<TABLE border="1"><COLGROUP>
                <COL><COL align="char" char="."><THEAD>
                <TR><TH>Key <TH>Command<TH>Key <TH>Command
                <TBODY>'''
        for i, j in help:
            m = '<TR><TD><b>%s</b>        <TD>%s<TD><b>%s</b>        <TD>%s' % (
                i[0], i[1], j[0], j[1])
            mess += m
        mess += '</TABLE'
        edit.setText(mess)
        edit.setReadOnly(True)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(edit)
        layout.addWidget(button)
        msg.setLayout(layout)
        msg.setMinimumSize(700, 800)
        msg.show()
        retval = msg.exec_()

    # keyboard jogging from key binding calls
    # double the rate if fast is true
    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                self.cmnd.abort()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        self.hal = halcomp
        self.w = widgets
        self.PATHS = paths
        self.current_mode = (None, None)
        self._last_count = 0
        self.rted = RichTextEditorDialog()
        self.STYLEEDITOR = SSE(widgets, paths)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')

        self.pin_mpg_in = self.hal.newpin('mpg-in', hal.HAL_S32, hal.HAL_IN)
        self.pin_mpg_in.value_changed.connect(lambda s: self.external_mpg(s))

        self.pin_cycle_start_in = self.hal.newpin('cycle-start-in',
                                                  hal.HAL_BIT, hal.HAL_IN)
        self.pin_cycle_start_in.value_changed.connect(
            lambda s: self.cycleStart(s))

        self.pin_abort = self.hal.newpin('abort', hal.HAL_BIT, hal.HAL_IN)
        self.pin_abort.value_changed.connect(lambda s: self.abort(s))

        self.wheel_x = self.hal.newpin('jog.wheel.x', hal.HAL_BIT, hal.HAL_OUT)
        self.wheel_y = self.hal.newpin('jog.wheel.y', hal.HAL_BIT, hal.HAL_OUT)
        self.wheel_z = self.hal.newpin('jog.wheel.z', hal.HAL_BIT, hal.HAL_OUT)

        self.jog_increment = self.hal.newpin('jog.wheel.incement',
                                             hal.HAL_FLOAT, hal.HAL_OUT)

        STATUS.connect(
            'feed-override-changed', lambda w, data: self.w.pushbutton_fo.
            setText('FO {0:.0f}%'.format(data)))
        STATUS.connect(
            'rapid-override-changed', lambda w, data: self.w.pushbutton_ro.
            setText('RO {0:.0f}%'.format(data)))
        STATUS.connect(
            'spindle-override-changed', lambda w, data: self.w.pushbutton_so.
            setText('SO {0:.0f}%'.format(data)))
        STATUS.connect('jogincrement-changed',
                       lambda w, incr, label: self.updateIncrementPin(incr))

        if self.w.PREFS_:
            try:
                value = self.w.PREFS_.getpref('DRO_Font', '', str,
                                              'CUSTOM_FORM_ENTRIES')
                if value != '':
                    font = QtGui.QFont()
                    font.fromString(value)
                    self.setDROFont(font)
            except:
                pass
            try:
                value = self.w.PREFS_.getpref('DRO_Color', '', str,
                                              'CUSTOM_FORM_ENTRIES')
                if value != '':
                    self.setDROColor(value)
            except:
                pass

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    def updateIncrementPin(self, incr):
        self.jog_increment.set(incr)

    #######################
    # callbacks from form #
    #######################

    def updateJogState(self):
        state = self.w.pushbutton_jog.isChecked()
        if state:
            ACTION.SET_MANUAL_MODE()
        selected = STATUS.get_selected_axis()
        for temp in INFO.AVAILABLE_AXES:
            if selected == temp:
                self['wheel_{}'.format(temp.lower())].set(state)
            else:
                self['wheel_{}'.format(temp.lower())].set(False)

    def colorDialog(self):
        color = QtWidgets.QColorDialog.getColor()
        self.setDROColor(color.name())

    def fontDialog(self):
        font, ok = QtWidgets.QFontDialog.getFont(self.w.dro_label_1.font())
        if ok:
            self.setDROFont(font)

    def togglePointer(self, data):
        if data:
            QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.BlankCursor)
        else:
            QtWidgets.QApplication.restoreOverrideCursor()

    #####################
    # general functions #
    #####################

    def setDROFont(self, font):
        for i in range(1, 10):
            self.w['dro_label_{}'.format(i)].setFont(font)

    def setDROColor(self, color):
        for i in range(1, 10):
            self.w['dro_label_{}'.format(i)].setStyleSheet(
                "QWidget { color: %s}" % color)

    def abort(self, state):
        if not state:
            return
        if STATUS.stat.interp_state == labvcnc.INTERP_IDLE:
            self.w.close()
        else:
            ACTION.ABORT()

    def cycleStart(self, state):
        print state, self.current_mode
        if state:
            tab = self.w.mainTab.currentWidget()
            if tab in (self.w.tab_auto, self.w.tab_graphics):
                print 'start cycle!', self.w.gcode_editor.get_line()
                ACTION.RUN(line=0)
            elif tab == self.w.tab_files:
                print 'load program'
                self.w.filemanager.load()
            elif tab == self.w.tab_mdi:
                print 'run MDI'
                self.w.mditouchy.run_command()

    # MPG scrolling of program or MDI history
    def external_mpg(self, count):
        diff = count - self._last_count
        if self.w.pushbutton_scroll.isChecked():
            if self.w.mainTab.currentWidget() == self.w.tab_auto:
                self.w.gcode_editor.jump_line(diff)
            elif self.w.mainTab.currentWidget() == self.w.tab_files:
                if diff < 0:
                    self.w.filemanager.down()
                else:
                    self.w.filemanager.up()
        elif self.w.pushbutton_fo.isChecked():
            scaled = (STATUS.stat.feedrate * 100 + diff)
            if scaled < 0: scaled = 0
            elif scaled > INFO.MAX_FEED_OVERRIDE:
                scaled = INFO.MAX_FEED_OVERRIDE
            ACTION.SET_FEED_RATE(scaled)
        elif self.w.pushbutton_ro.isChecked():
            scaled = (STATUS.stat.rapidrate * 100 + diff)
            if scaled < 0: scaled = 0
            elif scaled > 100: scaled = 100
            ACTION.SET_RAPID_RATE(scaled)
        elif self.w.pushbutton_so.isChecked():
            scaled = (STATUS.stat.spindle[0]['override'] * 100 + diff)
            if scaled < INFO.MIN_SPINDLE_OVERRIDE:
                scaled = INFO.MIN_SPINDLE_OVERRIDE
            elif scaled > INFO.MAX_SPINDLE_OVERRIDE:
                scaled = INFO.MAX_SPINDLE_OVERRIDE
            ACTION.SET_SPINDLE_RATE(scaled)
        self._last_count = count

    # keyboard jogging from key binding calls
    # double the rate if fast is true
    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            if STATUS.stat.interp_state == labvcnc.INTERP_IDLE:
                self.w.close()
            else:
                self.cmnd.abort()

    # Function keys
    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        if 'A' in INFO.AVAILABLE_AXES:
            self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        if 'A' in INFO.AVAILABLE_AXES:
            self.kb_jog(state, 3, -1, shift, linear=False)

    ###########################
    # **** closing event **** #
    ###########################
    def closing_cleanup__(self):
        if self.w.PREFS_:
            self.w.PREFS_.putpref('DRO_Font',
                                  self.w.dro_label_1.font().toString(), str,
                                  'CUSTOM_FORM_ENTRIES')
            color = self.w.dro_label_1.palette().color(
                QtGui.QPalette.Foreground).name()
            self.w.PREFS_.putpref('DRO_Color', color, str,
                                  'CUSTOM_FORM_ENTRIES')

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 17
0
class HandlerClass:
    def __init__(self, halcomp, widgets, paths):
        self.h = halcomp
        self.w = widgets
        self.PATHS = paths
        INIPATH = os.environ.get('INI_FILE_NAME', '/dev/null')
        self.inifile = linuxcnc.ini(INIPATH)
        self.STYLEEDITOR = SSE(widgets,paths)
        self.GCODES = GCodes(widgets)
        self.valid = QtGui.QDoubleValidator(0.0, 999.999, 3)
        
        KEYBIND.add_call('Key_F12','on_keycall_F12')
        KEYBIND.add_call('Key_Pause', 'on_keycall_pause')
        KEYBIND.add_call('Key_Plus', 'on_keycall_plus')
        KEYBIND.add_call('Key_Minus', 'on_keycall_minus')
                
        STAT.connect('general', self.dialog_return)
        STAT.connect('state-on', lambda w: self.enable_onoff(True))
        STAT.connect('state-off', lambda w: self.enable_onoff(False))
        STAT.connect('gcode-line-selected', lambda w, line: self.set_start_line(line))
        STAT.connect('hard-limits-tripped', self.hard_limit_tripped)
        STAT.connect('interp-idle', lambda w: self.set_start_line(0))
        STAT.connect('user-system-changed', self.user_system_changed)
        STAT.connect('file-loaded', self.file_loaded)
        STAT.connect('all-homed', self.all_homed)
        STAT.connect('not-all-homed', lambda w, list: self.set_dro_homed(False))

# some global variables
        self.axis_list = INFO.AVAILABLE_AXES
        self.max_linear_velocity = INFO.MAX_LINEAR_VELOCITY
        self.max_spindle_rpm = INFO.MAX_SPINDLE_SPEED
        self.system_list = ["G53","G54","G55","G56","G57","G58","G59","G59.1","G59.2","G59.3"]
        self.slow_jog_factor = 10
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.first_turnon = True
        self.onoff_list = ["frame_program", "frame_tool", "frame_dro"]
        self.axis_a_list = ["label_axis_a", "dro_axis_a", "action_zero_a", "axistoolbutton_a",
                            "action_home_a", "widget_jog_angular", "widget_increments_angular",
                            "a_plus_jogbutton", "a_minus_jogbutton"]

    def initialized__(self):
        self.init_pins()
        self.init_preferences()
        self.init_widgets()
        self.GCODES.setup_list()
        self.w.stackedWidget_log.setCurrentIndex(0)

        if "A" not in self.axis_list:
            for i in self.axis_a_list:
                self.w[i].hide()
            self.w.lbl_increments_linear.setText("INCREMENTS")

    #############################
    # SPECIAL FUNCTIONS SECTION #
    #############################
    def init_pins(self):
        pin = self.h.newpin("spindle_speed_fb", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.spindle_fb_changed)
        pin = self.h.newpin("spindle_amps", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.spindle_amps_changed)
        pin = self.h.newpin("spindle_power", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.spindle_power_changed)
        pin = self.h.newpin("spindle_fault", hal.HAL_U32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.spindle_fault_changed)
        pin = self.h.newpin("modbus-errors", hal.HAL_U32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.mb_errors_changed)
        
    def init_preferences(self):
        if not self.w.PREFS_:
            self.add_alarm("CRITICAL - no preference file found, enable preferences in screenoptions widget")
            return
        self.last_loaded_program = self.w.PREFS_.getpref('last_file_path', None, str,'BOOK_KEEPING')
        self.reload_tool = self.w.PREFS_.getpref('Tool to load', 0, int,'CUSTOM_FORM_ENTRIES')
        self.w.chk_reload_program.setChecked(self.w.PREFS_.getpref('Reload program', False, bool,'CUSTOM_FORM_ENTRIES'))
        self.w.chk_reload_tool.setChecked(self.w.PREFS_.getpref('Reload tool', False, bool,'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_keyboard.setChecked(self.w.PREFS_.getpref('Use keyboard', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_run_from_line.setChecked(self.w.PREFS_.getpref('Run from line', False, bool, 'CUSTOM_FORM_ENTRIES'))
        
    def closing_cleanup__(self):
        if not self.w.PREFS_: return
        self.w.PREFS_.putpref('Tool to load', self.w.statuslabel_tool.text().encode('utf-8'), int, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Reload program', self.w.chk_reload_program.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Reload tool', self.w.chk_reload_tool.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use keyboard', self.w.chk_use_keyboard.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Run from line', self.w.chk_run_from_line.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')

    def init_widgets(self):
        self.w.main_tab_widget.setCurrentIndex(0)
        self.w.slider_jog_linear.setMaximum(self.max_linear_velocity * 60)
        self.w.slider_jog_linear.setValue(INFO.DEFAULT_LINEAR_JOG_VEL)
        self.w.slider_jog_angular.setMaximum(INFO.MAX_ANGULAR_JOG_VEL)
        self.w.slider_jog_angular.setValue(INFO.DEFAULT_ANGULAR_JOG_VEL)
        self.w.slider_feed_ovr.setMaximum(INFO.MAX_FEED_OVERRIDE)
        self.w.slider_feed_ovr.setValue(100)
        self.w.slider_rapid_ovr.setMaximum(100)
        self.w.slider_rapid_ovr.setValue(100)
        self.w.slider_spindle_ovr.setMinimum(INFO.MIN_SPINDLE_OVERRIDE)
        self.w.slider_spindle_ovr.setMaximum(INFO.MAX_SPINDLE_OVERRIDE)
        self.w.slider_spindle_ovr.setValue(100)
        self.w.chk_override_limits.setChecked(False)
        self.w.chk_override_limits.setEnabled(False)
        self.w.filemanager.show()
        self.w.gcode_editor.hide()
        self.w.lbl_max_rapid.setText(str(self.max_linear_velocity * 60))
        self.w.lbl_search_vel.setText(self.inifile.find('TOOLSENSOR', 'SEARCH_VEL') or "200")
        self.w.lbl_probe_vel.setText(self.inifile.find('TOOLSENSOR', 'PROBE_VEL') or "50")
        self.w.lbl_max_probe.setText(self.inifile.find('TOOLSENSOR', 'MAXPROBE') or "10")
        self.w.lbl_touch_height.setText(self.inifile.find('TOOLSENSOR', 'TOUCH') or "50")
        self.w.lbl_laser_x.setText(self.inifile.find('LASER', 'X') or "100")
        self.w.lbl_laser_y.setText(self.inifile.find('LASER', 'Y') or "-10")
        self.w.lbl_home_x.setText(self.inifile.find('JOINT_0', 'HOME') or "50")
        self.w.lbl_home_y.setText(self.inifile.find('JOINT_1', 'HOME') or "50")
        #set up gcode list
        self.w.gcode_list.currentRowChanged.connect(self.list_row_changed)
        titles = mdiText.gcode_titles()
        for key in sorted(titles.iterkeys()):
            self.w.gcode_list.addItem(key + ' ' + titles[key])
        self.w.gcode_description.setReadOnly(True)

    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2):
#                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F4,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, QtWidgets.QLineEdit):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                if isinstance(receiver2, TOOL_TABLE):
                    flag = True
                    break
                if isinstance(receiver2, OFFSET_VIEW):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STAT.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self,event,is_pressed,shift,cntrl)
        except NameError as e:
            self.add_alarm('Exception in KEYBINDING: {}'.format (e))
        except Exception as e:
            LOG.error('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s'%(KEYBIND.convert(event),key)
            return False

    #########################
    # CALLBACKS FROM STATUS #
    #########################

    def spindle_fb_changed(self, data):
        rpm = int(self.h['spindle_speed_fb'])
        self.w.lbl_spindle_rpm.setText(str(rpm))
        if float(self.w.label_spindle_set.text()) > self.max_spindle_rpm:
            self.w.label_spindle_set.setProperty('overspeed', True)
        else:
            self.w.label_spindle_set.setProperty('overspeed', False)
        self.w.label_spindle_set.setStyle(self.w.label_spindle_set.style())

    def spindle_amps_changed(self, data):
        amps = "{:1.1f}".format(self.h['spindle_amps'])
        self.w.lbl_spindle_amps.setText(amps)

    def spindle_power_changed(self, data):
        power = "{:4.1f}".format(self.h['spindle_power'])
        self.w.lbl_spindle_power.setText(power)

    def spindle_fault_changed(self, data):
        fault = hex(self.h['spindle_fault'])
        self.w.lbl_spindle_fault.setText(fault)

    def mb_errors_changed(self, data):
        errors = self.h['modbus-errors']
        self.w.lbl_mb_errors.setText(str(errors))

    def dialog_return(self, w, message):
        rtn = message.get('RETURN')
        name = message.get('NAME')
        jog_code = bool(message.get('ID') == '_touchoff_')
        if jog_code and name == 'MESSAGE' and rtn is True:
            z_offset = float(self.w.lbl_touch_height.text())
            max_probe = self.w.lbl_max_probe.text()
            search_vel = self.w.lbl_search_vel.text()
            probe_vel = self.w.lbl_probe_vel.text()
            ACTION.CALL_MDI("G21 G49")
            ACTION.CALL_MDI("G10 L20 P0 Z0")
            ACTION.CALL_MDI("G91")
            command = "G38.2 Z-{} F{}".format(max_probe, search_vel)
            if ACTION.CALL_MDI_WAIT(command, 10) == -1: return
            if ACTION.CALL_MDI_WAIT("G1 Z4.0") == -1: return
            ACTION.CALL_MDI("G4 P0.5")
            command = "G38.2 Z-4.4 F{}".format(probe_vel)
            if ACTION.CALL_MDI_WAIT(command, 10) == -1: return
            command = "G10 L20 P0 Z{}".format(z_offset)
            ACTION.CALL_MDI(command)
            command = "G1 Z10.0 F{}".format(search_vel)
            ACTION.CALL_MDI_WAIT(command, 10)
            ACTION.CALL_MDI("G90")

    def user_system_changed(self, obj, data):
        sys = self.system_list[int(data)]
        self.w.actionbutton_rel.setText(sys)

    def file_loaded(self, obj, filename):
        if filename is not None:
            self.w.progressBar.setValue(0)
            self.last_loaded_program = filename
        else:
            self.add_alarm("Filename not valid")

    def all_homed(self, obj):
        self.set_dro_homed(True)
        if self.first_turnon is True:
            self.first_turnon = False
            if self.w.chk_reload_tool.isChecked():
                command = "M61 Q{}".format(self.reload_tool)
                ACTION.CALL_MDI(command)
            if self.last_loaded_program and self.w.chk_reload_program.isChecked():
                ACTION.OPEN_PROGRAM(self.last_loaded_program)
                self.w.filemanager.updateDirectoryView(self.last_loaded_program)
        
    def hard_limit_tripped(self, obj, tripped, list_of_tripped):
        self.w.chk_override_limits.setEnabled(tripped)
        if not tripped:
            self.w.chk_override_limits.setChecked(False)
    
    #######################
    # CALLBACKS FROM FORM #
    #######################

    # program frame
    def btn_start_clicked(self):
        if self.w.main_tab_widget.currentIndex() != 0:
            return
        if not STAT.is_auto_mode():
            self.add_alarm("Must be in AUTO mode to run a program")
            return
        self.w.btn_start.setProperty('running', True)
        self.w.btn_start.setStyle(self.w.btn_start.style())
        start_line = int(self.w.lbl_start_line.text().encode('utf-8'))
        self.add_alarm("Started program from line {}".format(start_line))
        ACTION.RUN(start_line)

    def btn_reload_file_clicked(self):
        if self.last_loaded_program:
            self.w.progressBar.setValue(0)
            ACTION.OPEN_PROGRAM(self.last_loaded_program)

    # tool frame
    def btn_go_home_clicked(self):
        ACTION.CALL_MDI_WAIT("G53 G0 Z0")
        command = "G53 G0 X{} Y{}".format(self.w.lbl_home_x.text(), self.w.lbl_home_y.text())
        ACTION.CALL_MDI_WAIT(command, 10)
 
    def btn_ref_laser_clicked(self):
        command = "G10 L20 P0 X{} Y{}".format(self.w.lbl_laser_x.text(), self.w.lbl_laser_y.text())
        ACTION.CALL_MDI(command)

    def btn_touchoff_clicked(self):
        if self.w.statuslabel_tool.text() == "0":
            self.add_alarm("Cannot touchoff with no tool loaded")
            return
        if not STAT.is_all_homed():
            self.add_alarm("Must be homed to perform tool touchoff")
            return
        max_probe = self.w.lbl_max_probe.text()
        self.add_alarm("Tool touchoff started")
        # instantiate dialog box
        info = "Jog to within {} mm of touch plate and click OK".format(max_probe)
        mess = {'NAME':'MESSAGE', 'ID':'_touchoff_', 'MESSAGE':'TOOL TOUCHOFF', 'MORE':info, 'TYPE':'OKCANCEL'}
        STAT.emit('dialog-request', mess)
        
    # override frame
    def slow_button_clicked(self, state):
        slider = self.w.sender().property('slider')
        current = self.w[slider].value()
        max = self.w[slider].maximum()
        if state:
            self.w.sender().setText("SLOW")
            self.w[slider].setMaximum(max / self.slow_jog_factor)
            self.w[slider].setValue(current / self.slow_jog_factor)
            self.w[slider].setPageStep(10)
        else:
            self.w.sender().setText("FAST")
            self.w[slider].setMaximum(max * self.slow_jog_factor)
            self.w[slider].setValue(current * self.slow_jog_factor)
            self.w[slider].setPageStep(100)

    # file tab
    def btn_gcode_edit_clicked(self, state):
        if not STAT.is_on_and_idle():
            return
        for x in ["load", "next", "prev"]:
            self.w["btn_file_{}".format(x)].setEnabled(not state)
        if state:
            self.w.filemanager.hide()
            self.w.gcode_editor.show()
            self.w.gcode_editor.editMode()
        else:
            self.w.filemanager.show()
            self.w.gcode_editor.hide()
            self.w.gcode_editor.readOnlyMode()

    # tool tab
    def btn_m61_clicked(self):
        checked = self.w.tooloffsetview.get_checked_list()
        if len(checked) > 1:
            self.add_alarm("Select only 1 tool to load")
        elif checked:
            ACTION.CALL_MDI("M61 Q{}".format(checked[0]))
        else:
            self.add_alarm("No tool selected")

    # alarm tab
    def btn_clear_alarms_clicked(self):
        STAT.emit('update-machine-log', None, 'DELETE')

    def btn_save_alarms_clicked(self):
        text = self.w.machinelog.toPlainText()
        filename = self.w.lbl_clock.text().encode('utf-8')
        filename = 'alarms_' + filename.replace(' ','_') + '.txt'
        with open(filename, 'w') as f:
            f.write(text)

    # gcode tab
    def list_row_changed(self, row):
        line = self.w.gcode_list.currentItem().text().encode('utf-8')
        text = line.split(' ')[0]
        desc = mdiText.gcode_descriptions(text) or 'No Match'
        self.w.gcode_description.clear()
        self.w.gcode_description.insertPlainText(desc)
        if text != 'null':
            words = mdiText.gcode_words()
            if text in words:
                parm = text + ' '
                for index, value in enumerate(words[text], start=0):
                    parm += value
                self.w.gcode_parameters.setText(parm)
            else:
                self.w.gcode_parameters.setText('')

    # settings tab
    def chk_override_limits_checked(self, state):
        if state:
            print("Override limits set")
            ACTION.SET_LIMITS_OVERRIDE()
        else:
            print("Override limits not set")

    def chk_run_from_line_checked(self, state):
        if not state:
            self.w.lbl_start_line.setText('1')

    #####################
    # GENERAL FUNCTIONS #
    #####################

    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STAT.is_man_mode() or not STAT.machine_is_on():
            self.add_alarm('Machine must be ON and in Manual mode to jog')
            return
        if linear:
            distance = STAT.get_jog_increment()
            rate = STAT.get_jograte()/60
        else:
            distance = STAT.get_jog_increment_angular()
            rate = STAT.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    def add_alarm(self, message):
        STAT.emit('update-machine-log', message, 'TIME')

    def alarm_added(self):
        self.w.led_alarm.setState(True)

    def tab_changed(self, index):
        self.w.btn_gcode_edit.setChecked(False)
        self.btn_gcode_edit_clicked(False)
        if index == 4:
            self.w.led_alarm.setState(False)

    def set_dro_homed(self, state):
        self.w.action_home_all.setProperty('homed', state)
        self.w.action_home_all.setStyle(self.w.action_home_all.style())
        for i in map(str.lower, self.axis_list):
            self.w["dro_axis_{}".format(i)].setProperty('homed', state)
            self.w["dro_axis_{}".format(i)].setStyle(self.w["dro_axis_{}".format(i)].style())

    def enable_onoff(self, state):
        for widget in self.onoff_list:
            self.w[widget].setEnabled(state)

    def set_start_line(self, line):
        if self.w.chk_run_from_line.isChecked():
            self.w.lbl_start_line.setText(str(line))
        else:
            self.w.lbl_start_line.setText('1')
            self.add_alarm('Run from line is disabled')

    def use_keyboard(self):
        if self.w.chk_use_keyboard.isChecked():
            return True
        else:
            self.add_alarm('Keyboard shortcuts are disabled')
            return False

    #####################
    # KEY BINDING CALLS #
    #####################

    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(True)

    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(False)

    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            ACTION.ABORT()

    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state and not STAT.is_all_homed() and self.use_keyboard():
            ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_pause(self,event,state,shift,cntrl):
        if state and STAT.is_auto_mode() and self.use_keyboard():
            ACTION.PAUSE()

    def on_keycall_XPOS(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 2, -1, shift)
    
    def on_keycall_plus(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_minus(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 3, -1, shift, False)

    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ##############################
    # required class boiler code #
    ##############################
    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 18
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        self.hal = halcomp
        self.w = widgets
        self.PATH = paths
        self._big_view = -1
        self.STYLEEDITOR = SSE(widgets, paths)
        self.flag = 0
        self.activeStyle = ''' { background-color: white;}'''
        self.defaultStyle = ''' { background-color: light blue;}'''
        self.activeWidgetDict = {
            'programPage': False,
            'userPage': False,
            'machinePage': False,
            'tooloffsetsPage': False,
            'loadPage': False,
            'mdiPage': False,
            'workoffsetsPage': False,
            'setupPage': False
        }
        self.current_mode = (None, None)
        self._last_count = 0

    ##########################################
    # Special Functions called from QTVCP
    ##########################################

    # For changing functions in widgets we can 'class patch'.
    # class patching must be done before the class is instantiated.
    #
    def class_patch__(self):
        GCODE.exitCall = self.editor_exit

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        STATUS.emit('play-sound',
                    'SPEAK This is a test screen for Haas styled QT lathe')
        KEYBIND.add_call('Key_F3', 'on_keycall_F3')
        KEYBIND.add_call('Key_F4', 'on_keycall_F4')
        KEYBIND.add_call('Key_F5', 'on_keycall_F5')
        KEYBIND.add_call('Key_F6', 'on_keycall_F6')
        KEYBIND.add_call('Key_F7', 'on_keycall_F7')
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')

        self.pin_mpg_in = self.hal.newpin('mpg-in', hal.HAL_S32, hal.HAL_IN)
        self.pin_mpg_in.value_changed.connect(lambda s: self.external_mpg(s))

        self.pin_cycle_start_in = self.hal.newpin('cycle-start-in',
                                                  hal.HAL_BIT, hal.HAL_IN)
        self.pin_cycle_start_in.value_changed.connect(
            lambda s: self.cycleStart(s))

        self.pin_abort = self.hal.newpin('abort', hal.HAL_BIT, hal.HAL_IN)
        self.pin_abort.value_changed.connect(lambda s: self.abort(s))

        self.pin_select_scroll = self.hal.newpin('select-scroll', hal.HAL_BIT,
                                                 hal.HAL_IN)
        self.pin_select_fo = self.hal.newpin('select-feedoverride',
                                             hal.HAL_BIT, hal.HAL_IN)
        self.pin_pin_select_ro = self.hal.newpin('select-rapidoverride',
                                                 hal.HAL_BIT, hal.HAL_IN)
        self.pin_select_so = self.hal.newpin('select-spindleoverride',
                                             hal.HAL_BIT, hal.HAL_IN)

    def before_loop__(self):
        STATUS.connect('state-estop', self.showclose)
        self.w.close()

    # This is because STATUS actual sends two of every message
    def showclose(self, w):
        self.flag += 1
        if self.flag == 2:
            self.w.close()
            self.flag = 0

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F5):
            raise

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    #######################
    # callbacks from form #
    #######################
    def toggle_prog(self):
        cur = self.w.mainPaneStack.currentIndex()
        if self.current_mode == ('program', 'run'):
            self.w.mainPaneStack.setCurrentIndex(1)
            self.set_active_mode('program', 'load')
        else:
            self.w.mainPaneStack.setCurrentIndex(0)
            self.set_active_mode('program', 'run')

    def toggle_MDI(self):
        self.w.mainPaneStack.setCurrentIndex(0)

        cur = self.w.widgetswitcher.currentIndex()
        if cur == 4:
            next = self.w.mdi_tab.currentIndex() + 1
            if next > self.w.mdi_tab.count() - 1:
                next = 0
            self.w.mdi_tab.setCurrentIndex(next)
        else:
            self.w.widgetswitcher.setCurrentIndex(4)
            self.w.mdi_tab.setCurrentIndex(0)
        self.set_active_mode('mdi', cur)

    def toggle_setup(self):
        self.w.widgetswitcher.setCurrentIndex(3)
        self.set_active_mode('setup', None)

    def toggle_dro(self):
        cur = self.w.droPaneStack.currentIndex()
        if cur == 0:
            self.w.droPaneStack.setCurrentIndex(cur + 1)
        else:
            self.w.droPaneStack.setCurrentIndex(0)

    def toggle_offsets(self):
        self.w.mainPaneStack.setCurrentIndex(0)
        cur = self.w.widgetswitcher.currentIndex()
        if cur == 2:
            self.set_active_mode('offsetPage', 'tool')
            self.w.widgetswitcher.setCurrentIndex(0)
        else:
            self.w.widgetswitcher.setCurrentIndex(2)
            self.set_active_mode('offsetPage', 'work')

    def set_edit_mode(self, num):
        if num == 2:
            self.w.gcodeeditor.editMode()
        else:
            self.w.gcodeeditor.readOnlyMode()

    def toggle_graphics(self):
        cur = self.w.mainLeftStack.currentIndex()
        if cur == 0:
            if self.w.widgetswitcher.get_current_number() == 0:
                self.w.widgetswitcher.show_default()
                self.w.mainLeftStack.setCurrentIndex(1)
            elif self.w.widgetswitcher.get_current_number() == 1:
                self.w.widgetswitcher.show_default()
                self.w.mainLeftStack.setCurrentIndex(0)
        elif cur == 1:
            self.w.mainLeftStack.setCurrentIndex(0)
            self.w.widgetswitcher.show_id_widget(1)

    #####################
    # general functions #
    #####################

    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    def editor_exit(self):
        self.w.gcodeeditor.exit()

    def set_active_mode(self, mode, index):
        #print mode,index
        def update(widget):
            for key, value in self.activeWidgetDict.iteritems():
                #print mode,key,value
                if key == widget:
                    print widget
                    self.w[key].setStyleSheet('#%s%s' %
                                              (key, self.activeStyle))
                    self.activeWidgetDict[key] = True
                elif value == True:
                    print 'switch off', key
                    self.w[key].setStyleSheet('#%s%s' %
                                              (key, self.defaultStyle))
                    self.activeWidgetDict[key] = False

        if mode == 'program':
            if index == 'run':
                update('programPage')
                self.w.label_mode.setText('Operation-Run Program')
            else:
                update('loadPage')
                self.w.label_mode.setText('Operation-Load Program')
        elif mode == 'setup':
            update('setupPage')
            self.w.label_mode.setText('Operation- Manual Setup')
        elif mode == 'mdi':
            update('mdiPage')
            self.w.label_mode.setText('Operation- MDI Control')
        elif mode == 'offsetPage':
            if index == 'tool':
                update('tooloffsetsPage')
            elif index == 'work':
                update('workoffsetsPage')
        else:
            print('mode/index not recognized')
            return
        self.current_mode = (mode, index)

    def abort(self, state):
        if not state:
            return
        if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
            self.w.close()
        else:
            ACTION.ABORT()

    def cycleStart(self, state):
        print state, self.current_mode
        if state:
            if self.current_mode[0] == 'program':
                if self.current_mode[1] == 'run':
                    print 'start cycle!', self.w.gcode_editor.get_line()
                    ACTION.RUN(line=0)
                elif self.current_mode[1] == 'load':
                    print 'load program'
                    self.w.filemanager.load()
            elif self.current_mode[0] == 'mdi':
                self.w.mdihistory.run_command()

    # MPG scolling of program or MDI history
    def external_mpg(self, count):
        diff = count - self._last_count
        if self.pin_select_scroll.get():
            if self.current_mode[0] == 'program':
                if self.current_mode[1] == 'run':
                    self.w.gcode_editor.jump_line(diff)
                elif self.current_mode[1] == 'load':
                    if diff < 0:
                        self.w.filemanager.down()
                    else:
                        self.w.filemanager.up()
            elif self.current_mode[0] == 'mdi':
                if diff < 0:
                    self.w.mdihistory.line_down()
                else:
                    self.w.mdihistory.line_up()
        elif self.pin_select_fo.get():
            scaled = (STATUS.stat.feedrate * 100 + diff)
            if scaled < 0: scaled = 0
            elif scaled > INFO.MAX_FEED_OVERRIDE:
                scaled = INFO.MAX_FEED_OVERRIDE
            ACTION.SET_FEED_RATE(scaled)
        elif self.pin_pin_select_ro.get():
            scaled = (STATUS.stat.rapidrate * 100 + diff)
            if scaled < 0: scaled = 0
            elif scaled > 100: scaled = 100
            ACTION.SET_RAPID_RATE(scaled)
        elif self.pin_select_so.get():
            scaled = (STATUS.stat.spindle[0]['override'] * 100 + diff)
            if scaled < INFO.MIN_SPINDLE_OVERRIDE:
                scaled = INFO.MIN_SPINDLE_OVERRIDE
            elif scaled > INFO.MAX_SPINDLE_OVERRIDE:
                scaled = INFO.MAX_SPINDLE_OVERRIDE
            ACTION.SET_SPINDLE_RATE(scaled)
        self._last_count = count

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            self.abort(state)

    # dialogs
    def on_keycall_F3(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'ORIGINOFFSET'})

    def on_keycall_F4(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'CAMVIEW'})

    def on_keycall_F5(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'MACROTAB'})

    def on_keycall_F6(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'TOOLOFFSET'})

    def on_keycall_F7(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'VERSAPROBE'})

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    ###########################
    # **** closing event **** #
    ###########################
    def closing_cleanup__(self):
        pass

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 19
0
 def __init__(self, halcomp,widgets,paths):
     self.hal = halcomp
     self.w = widgets
     self.PATH = paths
     self._big_view = -1
     self.STYLEEDITOR = SSE(widgets,paths)
Esempio n. 20
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        self.hal = halcomp
        self.w = widgets
        self.PATHS = paths
        self.STYLEEDITOR = SSE(widgets, paths)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = False
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    #######################
    # callbacks from form #
    #######################

    #####################
    # general functions #
    #####################

    # keyboard jogging from key binding calls
    # double the rate if fast is true
    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                self.cmnd.abort()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 21
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp,widgets,paths):
        self.hal = halcomp
        self.w = widgets
        self.PATHS = paths
        self.STYLEEDITOR = SSE(widgets,paths)
        global TOOLBAR
        TOOLBAR = ToolBarActions(widgets)
        STATUS.connect('general',self.return_value)
        STATUS.connect('motion-mode-changed',self.motion_mode)
        STATUS.connect('user-system-changed', self._set_user_system_text)
        STATUS.connect('actual-spindle-speed-changed',self.update_spindle)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    def class_patch__(self):
        GCODE.exitCall = self.editor_exit

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12','on_keycall_F12')
        KEYBIND.add_call('Key_QuoteLeft','on_keycall_feedoverride',0)
        KEYBIND.add_call('Key_1','on_keycall_feedoverride',10)
        KEYBIND.add_call('Key_2','on_keycall_feedoverride',20)
        KEYBIND.add_call('Key_3','on_keycall_feedoverride',30)
        KEYBIND.add_call('Key_4','on_keycall_feedoverride',40)
        KEYBIND.add_call('Key_5','on_keycall_feedoverride',50)
        KEYBIND.add_call('Key_6','on_keycall_feedoverride',60)
        KEYBIND.add_call('Key_7','on_keycall_feedoverride',70)
        KEYBIND.add_call('Key_8','on_keycall_feedoverride',80)
        KEYBIND.add_call('Key_9','on_keycall_feedoverride',90)
        KEYBIND.add_call('Key_0','on_keycall_feedoverride',100)

        #KEYBIND.add_call('Key_AsciiTilde','on_keycall_spindleoverride',0)
        #KEYBIND.add_call('Key_Exclam','on_keycall_spindleoverride',10)
        #KEYBIND.add_call('Key_At','on_keycall_spindleoverride',20)
        #KEYBIND.add_call('Key_NumberSign','on_keycall_spindleoverride',30)
        #KEYBIND.add_call('Key_DollarSign','on_keycall_spindleoverride',40)
        #KEYBIND.add_call('Key_Percent','on_keycall_spindleoverride',50)
        KEYBIND.add_call('Key_AsciiCircum','on_keycall_spindleoverride',60)
        KEYBIND.add_call('Key_Ampersand','on_keycall_spindleoverride',70)
        KEYBIND.add_call('Key_Asterisk','on_keycall_spindleoverride',80)
        KEYBIND.add_call('Key_Parenleft','on_keycall_spindleoverride',90)
        KEYBIND.add_call('Key_ParenRight','on_keycall_spindleoverride',100)
        KEYBIND.add_call('Key_Underscore','on_keycall_spindleoverride',110)

        TOOLBAR.configure_submenu(self.w.menuRecent, 'recent_submenu')
        TOOLBAR.configure_submenu(self.w.menuHoming, 'home_submenu')
        TOOLBAR.configure_submenu(self.w.menuUnhome, 'unhome_submenu')
        TOOLBAR.configure_submenu(self.w.menuZeroCoordinateSystem, 'zero_systems_submenu')
        TOOLBAR.configure_action(self.w.actionEstop, 'estop')
        TOOLBAR.configure_action(self.w.actionMachineOn, 'power')
        TOOLBAR.configure_action(self.w.actionOpen, 'load')
        TOOLBAR.configure_action(self.w.actionReload, 'Reload')
        TOOLBAR.configure_action(self.w.actionRun, 'run')
        TOOLBAR.configure_action(self.w.actionPause, 'pause')
        TOOLBAR.configure_action(self.w.actionStop, 'abort')
        TOOLBAR.configure_action(self.w.actionSkip, 'block_delete')
        TOOLBAR.configure_action(self.w.actionOptionalStop, 'optional_stop')
        TOOLBAR.configure_action(self.w.actionZoomIn, 'zoom_in')
        TOOLBAR.configure_action(self.w.actionZoomOut, 'zoom_out')
        TOOLBAR.configure_action(self.w.actionFrontView, 'view_x')
        TOOLBAR.configure_action(self.w.actionSideView, 'view_y')
        TOOLBAR.configure_action(self.w.actionRotatedView, 'view_z2')
        TOOLBAR.configure_action(self.w.actionTopView, 'view_z')
        TOOLBAR.configure_action(self.w.actionPerspectiveView, 'view_p')
        TOOLBAR.configure_action(self.w.actionClearPlot, 'view_clear')
        TOOLBAR.configure_action(self.w.actionShowOffsets, 'show_offsets')
        TOOLBAR.configure_action(self.w.actionQuit, 'Quit', lambda d:self.w.close())
        TOOLBAR.configure_action(self.w.actionShutdown, 'system_shutdown')
        TOOLBAR.configure_action(self.w.actionProperties, 'gcode_properties')
        TOOLBAR.configure_action(self.w.actionCalibration, 'load_calibration')
        TOOLBAR.configure_action(self.w.actionStatus, 'load_status')
        TOOLBAR.configure_action(self.w.actionHalshow, 'load_halshow')
        TOOLBAR.configure_action(self.w.actionHalmeter, 'load_halmeter')
        TOOLBAR.configure_action(self.w.actionHalscope, 'load_halscope')
        TOOLBAR.configure_action(self.w.actionAbout, 'about')
        TOOLBAR.configure_action(self.w.actionTouchoffWorkplace, 'touchoffworkplace')
        TOOLBAR.configure_action(self.w.actionEdit, 'edit', self.edit)
        TOOLBAR.configure_action(self.w.actionTouchoffFixture, 'touchofffixture')
        TOOLBAR.configure_action(self.w.actionRunFromLine, 'runfromline')
        TOOLBAR.configure_action(self.w.actionToolOffsetDialog, 'tooloffsetdialog')
        TOOLBAR.configure_action(self.w.actionOriginOffsetDialog, 'originoffsetdialog')
        self.w.actionQuickRef.triggered.connect(self.quick_reference)
        self.w.actionMachineLog.triggered.connect(self.launch_log_dialog)
        if not INFO.HOME_ALL_FLAG:
            self.w.actionButton_home.setText("Home Selected")
            self.w.actionButton_home.set_home_select(True)
        self.w.rpm_bar = QtWidgets.QProgressBar()
        self.w.rpm_bar.setRange(0, INFO.MAX_SPINDLE_SPEED)
        self.w.rightTab.setCornerWidget(self.w.rpm_bar)

    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2,
                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F5,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                receiver2 = receiver2.parent()
            if flag:
                if isinstance(receiver2, GCODE):
                    # send events to gcode widget if in edit mode
                    # else do our keybindings
                    if self.w.actionEdit.isChecked() == True:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            b = KEYBIND.call(self,event,is_pressed,shift,cntrl)
            event.accept()
            return True
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format (e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s'%(KEYBIND.convert(event),key)
            return False

    def closing_cleanup__(self):
        TOOLBAR.saveRecentPaths()

    ########################
    # callbacks from STATUS #
    ########################

    # process the STATUS return message from set-tool-offset
    def return_value(self, w, message):
        num = message['RETURN']
        code = bool(message['ID'] == 'FORM__')
        name = bool(message['NAME'] == 'ENTRY')
        if num is not None and code and name:
            LOG.debug('message return:{}'.format (message))
            axis = message['AXIS']
            fixture = message['FIXTURE']
            ACTION.SET_TOOL_OFFSET(axis,num,fixture)
            STATUS.emit('update-machine-log', 'Set tool offset of Axis %s to %f' %(axis, num), 'TIME')

    def motion_mode(self, w, mode):
        #print STATUS.stat.joints
        #print STATUS.stat.kinematics_type
        #print INFO.AVAILABLE_AXES
        #print INFO.GET_NAME_FROM_JOINT
        if mode == linuxcnc.TRAJ_MODE_COORD:
            pass
        # Joint mode
        elif mode == linuxcnc.TRAJ_MODE_FREE:
            if STATUS.stat.kinematics_type == linuxcnc.KINEMATICS_IDENTITY:
                self.show_axes()
            else:
                self.show_joints()
        elif mode == linuxcnc.TRAJ_MODE_TELEOP:
            self.show_axes()

    def update_spindle(self,w,data):
        self.w.rpm_bar.setInvertedAppearance(bool(data<0))
        self.w.rpm_bar.setFormat('{0:d} RPM'.format(int(data)))
        self.w.rpm_bar.setValue(abs(data))

    #######################
    # callbacks from form #
    #######################

    def leftTabChanged(self, num):
        if num == 0:
            ACTION.SET_MANUAL_MODE()

    #####################
    # general functions #
    #####################

    def show_joints(self):
        for i in range(0,9):
            if i in INFO.AVAILABLE_JOINTS:
                self.w['ras_label_%s'%i].show()
                self.w['ras_%s'%i].show()
                self.w['ras_label_%s'%i].setText('J%d'%i)
                try:
                    self.w['machine_label_j%d'%i].setText('<html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Joint %d:</span></p></body></html>'%i)
                except:
                    pass
                continue
            self.w['ras_label_%s'%i].hide()
            self.w['ras_%s'%i].hide()

    def show_axes(self):
        for i in range(0,9):
            j = INFO.GET_NAME_FROM_JOINT.get(i)
            if j and len(j) == 1:
                self.w['ras_label_%s'%i].show()
                self.w['ras_%s'%i].show()
                self.w['ras_label_%s'%i].setText('%s'%j)
                try:
                    self.w['machine_label_j%d'%i].setText('<html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Machine %s:</span></p></body></html>' %j)
                except:
                    pass
                continue
            self.w['ras_label_%s'%i].hide()
            self.w['ras_%s'%i].hide()

    def _set_user_system_text(self, w, data):
        convert = { 1:"G54 ", 2:"G55 ", 3:"G56 ", 4:"G57 ", 5:"G58 ", 6:"G59 ", 7:"G59.1 ", 8:"G59.2 ", 9:"G59.3 "}
        unit = convert[int(data)]
        for i in ('x','y','z'):
            self.w['dro_label_g5x_%s'%i].imperial_template = unit + i.upper() + '%9.4f'
            self.w['dro_label_g5x_%s'%i].metric_template = unit + i.upper() + '%10.3f'
            self.w['dro_label_g5x_%s'%i].update_units()
        self.w.dro_label_g5x_r.angular_template = unit + 'R      %3.2f'
        self.w.dro_label_g5x_r.update_units()
        self.w.dro_label_g5x_r.update_rotation(None, STATUS.stat.rotation_xy)

    def editor_exit(self):
        self.w.gcode_editor.exit()
        self.w.actionEdit.setChecked(False)
        self.edit(None,False)

    def edit(self, widget, state):
        if state:
            self.w.gcode_editor.editMode()
            self.w.gcode_editor.setMaximumHeight(1000)
            self.w.frame.hide()
            self.w.rightTab.hide()
        else:
            self.w.gcode_editor.readOnlyMode()
            self.w.gcode_editor.setMaximumHeight(500)
            self.w.frame.show()
            self.w.rightTab.show()

    def quick_reference(self):
        help1 = [
    ("F1", _("Emergency stop")),
    ("F2", _("Turn machine on")),
    ("", ""),
    ("X", _("Activate first axis")),
    ("Y", _("Activate second axis")),
    ("Z", _("Activate third axis")),
    ("A", _("Activate fourth axis")),
    ("` or 0,1..8", _("Activate first through ninth joint <br>if joints radiobuttons visible")),
    ("", _("")),
    ("`,1..9,0", _("Set Feed Override from 0% to 100%")),
    ("", _("if axes radiobuttons visible")),
    (_(", and ."), _("Select jog speed")),
    (_("< and >"), _("Select angular jog speed")),
    (_("I, Shift-I"), _("Select jog increment")),
    ("C", _("Continuous jog")),
    (_("Home"), _("Send active joint home")),
    (_("Ctrl-Home"), _("Home all joints")),
    (_("Shift-Home"), _("Zero G54 offset for active axis")),
    (_("End"), _("Set G54 offset for active axis")),
    (_("Ctrl-End"), _("Set tool offset for loaded tool")),
    ("-, =", _("Jog active axis or joint")),
    (";, '", _("Select Max velocity")),

    ("", ""),
    (_("Left, Right"), _("Jog first axis or joint")),
    (_("Up, Down"), _("Jog second axis or joint")),
    (_("Pg Up, Pg Dn"), _("Jog third axis or joint")),
    (_("Shift+above jogs"), _("Jog at traverse speed")),
    ("[, ]", _("Jog fourth axis or joint")),

    ("", ""),
    ("D", _("Toggle between Drag and Rotate mode")),
    (_("Left Button"), _("Pan, rotate or select line")),
    (_("Shift+Left Button"), _("Rotate or pan")),
    (_("Right Button"), _("Zoom view")),
    (_("Wheel Button"), _("Rotate view")),
    (_("Rotate Wheel"), _("Zoom view")),
    (_("Control+Left Button"), _("Zoom view")),
]
        help2 = [
    ("F3", _("Manual control")),
    ("F5", _("Code entry (MDI)")),
    (_("Control-M"), _("Clear MDI history")),
    (_("Control-H"), _("Copy selected MDI history elements")),
    ("",          _("to clipboard")),
    (_("Control-Shift-H"), _("Paste clipboard to MDI history")),
    ("L", _("Override Limits")),
    ("", ""),
    ("O", _("Open program")),
    (_("Control-R"), _("Reload program")),
    (_("Control-S"), _("Save g-code as")),
    ("R", _("Run program")),
    ("T", _("Step program")),
    ("P", _("Pause program")),
    ("S", _("Resume program")),
    ("ESC", _("Stop running program, or")),
    ("", _("stop loading program preview")),
    ("", ""),
    ("F7", _("Toggle mist")),
    ("F8", _("Toggle flood")),
    ("B", _("Spindle brake off")),
    (_("Shift-B"), _("Spindle brake on")),
    ("F9", _("Turn spindle clockwise")),
    ("F10", _("Turn spindle counterclockwise")),
    ("F11", _("Turn spindle more slowly")),
    ("F12", _("Turn spindle more quickly")),
    (_("Control-K"), _("Clear live plot")),
    ("V", _("Cycle among preset views")),
    ("F4", _("Cycle among preview, DRO, and user tabs")),
    ("@", _("toggle Actual/Commanded")),
    ("#", _("toggle Relative/Machine")),
    (_("Ctrl-Space"), _("Clear notifications")),
    (_("Alt-F, M, V"), _("Open a Menu")),
]
        help =  zip(help1,help2)
        msg = QtWidgets.QDialog()
        msg.setWindowTitle("Quick Reference")
        button = QtWidgets.QPushButton("Ok")
        button.clicked.connect(lambda: msg.close())
        edit = QtWidgets.QTextEdit()
        edit.setLineWrapMode(0)

        mess = '''<TABLE border="1"><COLGROUP>
                <COL><COL align="char" char="."><THEAD>
                <TR><TH>Key <TH>Command<TH>Key <TH>Command
                <TBODY>'''
        for i,j in help:
            m='<TR><TD><b>%s</b>        <TD>%s<TD><b>%s</b>        <TD>%s'%(i[0],i[1],j[0],j[1])
            mess += m
        mess += '</TABLE'
        edit.setText(mess)
        edit.setReadOnly(True)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(edit)
        layout.addWidget(button)
        msg.setLayout(layout)
        msg.setMinimumSize(700,800)
        msg.show()
        retval = msg.exec_()

    def launch_log_dialog(self):
        STATUS.emit('dialog-request',{'NAME':'MACHINELOG', 'ID':'_qtaxis_handler_'})

    # keyboard jogging from key binding calls
    # double the rate if fast is true 
    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte()/60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())
    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())
    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)
    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                ACTION.ABORT()

    # Linear Jogging
    def on_keycall_XPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    def on_keycall_feedoverride(self,event,state,shift,cntrl,value):
        if state:
            ACTION.SET_FEED_RATE(value)

    def on_keycall_spindleoverride(self,event,state,shift,cntrl,value):
        if state:
            ACTION.SET_SPINDLE_RATE(value)

    ###########################
    # **** closing event **** #
    ###########################

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)
    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 22
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        self.hal = halcomp
        self.w = widgets
        self.PATH = paths.CONFIGPATH
        self.IMAGE_PATH = paths.IMAGEDIR
        self._big_view = -1
        self.STYLEEDITOR = SSE(widgets, paths)

    ##########################################
    # Special Functions called from QTVCP
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        STATUS.emit('play-alert', 'SPEAK This is a test screen for Qt V C P')
        KEYBIND.add_call('Key_F3', 'on_keycall_F3')
        KEYBIND.add_call('Key_F4', 'on_keycall_F4')
        KEYBIND.add_call('Key_F5', 'on_keycall_F5')
        KEYBIND.add_call('Key_F6', 'on_keycall_F6')
        KEYBIND.add_call('Key_F7', 'on_keycall_F7')
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')
        self.w.tooloffsetdialog._geometry_string = '0 0 600 400 onwindow '

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F5):
            if isinstance(receiver, OFFVIEW_WIDGET) or \
                isinstance(receiver, MDI_WIDGET) or isinstance(receiver, TOOLVIEW_WIDGET):
                if is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                return True
            elif isinstance(receiver, GCODE) and STATUS.is_man_mode() == False:
                if is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                return True
            elif isinstance(receiver, QDialog):
                print 'dialog'
                return True

        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    #######################
    # callbacks from form #
    #######################
    def widget_switch(self, data):
        self.w.widgetswitcher.show_next()

    def set_edit_mode(self, num):
        if num == 1:
            self.w.gcodeeditor.editMode()
        else:
            self.w.gcodeeditor.readOnlyMode()

    #####################
    # general functions #
    #####################

    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    # called from 'machine on' button's python command in designer
    # to test that function
    def test_function(self, text=None):
        print text

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                ACTION.ABORT()

    # dialogs
    def on_keycall_F3(self, event, state, shift, cntrl):
        if state:
            self.w.originoffsetdialog.load_dialog()

    def on_keycall_F4(self, event, state, shift, cntrl):
        if state:
            self.w.camviewdialog.load_dialog()

    def on_keycall_F5(self, event, state, shift, cntrl):
        if state:
            self.w.macrotabdialog.load_dialog()

    def on_keycall_F6(self, event, state, shift, cntrl):
        if state:
            self.w.tooloffsetdialog.load_dialog()

    def on_keycall_F7(self, event, state, shift, cntrl):
        if state:
            self.w.versaprobedialog.load_dialog()

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    ###########################
    # **** closing event **** #
    ###########################
    def closing_cleanup__(self):
        pass

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 23
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp,widgets,paths):
        self.hal = halcomp
        self.w = widgets
        self.PATHS = paths
        self.STYLEEDITOR = SSE(widgets,paths)
        self.picked_line = None
        STATUS.connect('general',self.return_value)
        STATUS.connect('graphics-line-selected', self.set_picked_line)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12','on_keycall_F12')

    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2,
                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F5,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = False
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        if event.isAutoRepeat():return True

        # ok if we got here then try keybindings function calls
        # KEYBINDING will call functions from handler file as
        # registered by KEYBIND.add_call(KEY,FUNCTION) above
        return KEYBIND.manage_function_calls(self,event,is_pressed,key,shift,cntrl)

    ########################
    # callbacks from STATUS #
    ########################
    # process the STATUS return message for run-from-line
    def return_value(self, obj, message):
        num = message['RETURN']
        code = bool(message['ID'] == '_RunFromLine_')
        name = bool(message['NAME'] == 'CALCULATOR')
        if num is not None and code and name:
            ACTION.RUN(int(num))

    def set_picked_line(self, obj, line):
        self.picked_line = line

    #######################
    # callbacks from form #
    #######################
    def full_screen(self, state):
        if state:
            self.w.stackedWidget_0.setCurrentIndex(1)
            self.w.widgetswitcher.show_id_widget(1)
        else:
            self.w.stackedWidget_0.setCurrentIndex(0)
            self.w.widgetswitcher.show_id_widget(0)

    def slow_jog_slider_changed(self, rate):
        if self.w.pbtn_jog_rate_slow.isChecked():
            ACTION.SET_JOG_RATE(rate)
    def fast_jog_slider_changed(self, rate):
        if self.w.pbtn_jog_rate_fast.isChecked():
            ACTION.SET_JOG_RATE(rate)

    def set_slow_rate(self, state):
        if state:
            ACTION.SET_JOG_RATE(self.w.scrb_jog_linear_slow.value())
    def set_fast_rate(self, state):
        if state:
            ACTION.SET_JOG_RATE(self.w.scrb_jog_linear_fast.value())

    def run_from_line_clicked(self):
        mess = {'NAME':'CALCULATOR','ID':'_RunFromLine_',
             'PRELOAD':self.picked_line,
               'TITLE':'Run From Line Dialog'}
        ACTION.CALL_DIALOG('dialog-request', mess)

    #####################
    # general functions #
    #####################

    # keyboard jogging from key binding calls
    # double the rate if fast is true 
    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte()/60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())
    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())
    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)
    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                ACTION.ABORT()

    # Linear Jogging
    def on_keycall_XPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)
    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 24
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        # some global variables
        self.hal = halcomp
        self.w = widgets
        self.PATH = paths
        self._big_view = -1
        self.flag = 0
        self.activeStyle = ''' { background-color: white;}'''
        self.defaultStyle = ''' { background-color: light blue;}'''
        self.activeWidgetDict = {
            'programPage': False,
            'userPage': False,
            'machinePage': False,
            'tooloffsetsPage': False,
            'loadPage': False,
            'mdiPage': False,
            'workoffsetsPage': False,
            'setupPage': False
        }
        self.current_mode = (None, None)
        self._last_count = 0
        self.run_time = 0
        self.time_tenths = 0
        self.timerOn = False
        self.slow_jog_factor = 10

        self.STYLEEDITOR = SSE(widgets, paths)
        self.GCODES = GCodes()

        STATUS.connect('periodic', lambda w: self.update_runtimer())
        STATUS.connect('command-running', lambda w: self.start_timer())
        STATUS.connect('command-stopped', lambda w: self.stop_timer())
        STATUS.connect("metric-mode-changed",
                       lambda w, d: self.mode_changed(d))
        STATUS.connect('state-off',
                       lambda w: self.w.pushbutton_metric.setEnabled(False))
        STATUS.connect('state-estop',
                       lambda w: self.w.pushbutton_metric.setEnabled(False))
        STATUS.connect(
            'interp-idle', lambda w: self.w.pushbutton_metric.setEnabled(
                self.homed_on_test()))
        STATUS.connect('interp-run',
                       lambda w: self.w.pushbutton_metric.setEnabled(False))
        STATUS.connect('all-homed',
                       lambda w: self.w.pushbutton_metric.setEnabled(True))
        STATUS.connect(
            'not-all-homed',
            lambda w, data: self.w.pushbutton_metric.setEnabled(False))

    ##########################################
    # Special Functions called from QTVCP
    ##########################################

    # For changing functions in widgets we can 'class patch'.
    # class patching must be done before the class is instantiated.
    #
    def class_patch__(self):
        GCODE.exitCall = self.editor_exit
        # patch filemanager so we can trap single click loading
        # (doesn't work well on a touchscreen)
        # you can only load using a button defined in designer now
        # keep a reference to the original function as 'superLoad'
        FILEMGR.superLoad = FILEMGR.load
        FILEMGR.load = self.FMGRnoop

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        STATUS.emit('play-sound',
                    'SPEAK This is a test screen for Haas styled QT lathe')
        KEYBIND.add_call('Key_F3', 'on_keycall_F3')
        KEYBIND.add_call('Key_F4', 'on_keycall_F4')
        KEYBIND.add_call('Key_F5', 'on_keycall_F5')
        KEYBIND.add_call('Key_F6', 'on_keycall_F6')
        KEYBIND.add_call('Key_F7', 'on_keycall_F7')
        KEYBIND.add_call('Key_F9', 'on_keycall_F9')
        KEYBIND.add_call('Key_F11', 'on_keycall_F11')
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')
        TOOLBAR.configure_action(self.w.actionCalculatorDialog,
                                 'calculatordialog')
        TOOLBAR.configure_submenu(self.w.menuGridSize, 'grid_size_submenu')
        TOOLBAR.configure_action(self.w.actionToolOffsetDialog,
                                 'tooloffsetdialog')
        TOOLBAR.configure_action(self.w.actionReload, 'Reload')
        TOOLBAR.configure_statusbar(self.w.statusbar, 'message_controls')
        self.w.pushbutton_metric.clicked[bool].connect(self.change_mode)

        # web view widget for SETUP SHEET page
        self.web_view = QWebView()
        self.w.verticalLayout_setup.addWidget(self.web_view)
        self.set_default_html()

        self.GCODES.setup_list()
        self.w.gcode_editor.hide()

    def before_loop__(self):
        STATUS.connect('state-estop', lambda q: self.w.close())

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F5, QtCore.Qt.Key_F6, QtCore.Qt.Key_F7,
                        QtCore.Qt.Key_F11, QtCore.Qt.Key_F12):
            raise

        if event.isAutoRepeat(): return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    ########################
    # callbacks from STATUS #
    ########################
    def runtime_sec_changed(self, data):
        text = "{:02d}:{:02d}:{:02d}".format(self.h['runtime_hrs'],
                                             self.h['runtime_min'],
                                             self.h['runtime_sec'])
        self.w.lbl_runtime.setText(text)

    def file_loaded(self, obj, filename):
        if filename is not None:
            self.w.progressBar.setValue(0)
            self.last_loaded_program = filename
        else:
            self.add_alarm("Filename not valid")

    def all_homed(self, obj):
        self.set_dro_homed(True)
        if self.first_turnon is True:
            self.first_turnon = False
            if self.w.chk_reload_tool.isChecked():
                STATUS.emit('update-machine-log',
                            'PreLoad Tool #{}: '.format(self.reload_tool),
                            'TIME')
                command = "M61 Q{}".format(self.reload_tool)
                ACTION.CALL_MDI(command)
            if self.last_loaded_program is not None and self.w.chk_reload_program.isChecked(
            ):
                STATUS.emit('update-machine-log',
                            'PreLoading NGC: ' + self.last_loaded_program,
                            'TIME')
                ACTION.OPEN_PROGRAM(self.last_loaded_program)
                self.w.filemanager.updateDirectoryView(
                    self.last_loaded_program)

    def not_all_homed(self, obj, list):
        self.home_all = False
        self.w.lbl_home_all.setText("HOME\nALL")
        for i in INFO.AVAILABLE_JOINTS:
            if str(i) in list:
                axis = INFO.GET_NAME_FROM_JOINT.get(i).lower()
                try:
                    self.w["dro_axis_{}".format(axis)].setProperty(
                        'homed', False)
                    self.w["dro_axis_{}".format(axis)].setStyle(
                        self.w["dro_axis_{}".format(axis)].style())
                except:
                    pass

    #######################
    # callbacks from form #
    #######################
    def percentLoaded(self, fraction):
        if fraction < 1:
            self.w.progressBar.setValue(0)
            self.w.progressBar.setFormat('')
        else:
            self.w.progressBar.setValue(fraction)
            self.w.progressBar.setFormat('Loading: {}%'.format(fraction))

    def percentCompleted(self, fraction):
        self.w.progressBar.setValue(fraction)
        if fraction < 1:
            self.w.progressBar.setFormat('')
        else:
            self.w.progressBar.setFormat('Completed: {}%'.format(fraction))

    def toggle_prog(self):
        if self.current_mode == ('program', 'run'):
            self.set_active_mode('program', 'load')
        else:
            self.set_active_mode('program', 'run')

    def toggle_MDI(self):
        self.set_active_mode('mdi', None)

    def toggle_setup(self):
        self.set_active_mode('setup', None)

    def toggle_dro(self):
        next = self.w.droPaneStack.currentIndex() + 1
        if next == self.w.droPaneStack.count():
            self.w.droPaneStack.setCurrentIndex(0)
        else:
            self.w.droPaneStack.setCurrentIndex(next)

    def toggle_offsets(self):
        self.set_active_mode('offsetPage', None)

    def set_edit_mode(self, num):
        if num == 2:
            self.w.gcodeeditor.editMode()
        else:
            self.w.gcodeeditor.readOnlyMode()

    def toggle_graphics(self):
        self.set_active_mode('graphics', None)

    # tool tab
    def btn_m61_clicked(self):
        checked = self.w.tooloffsetview.get_checked_list()
        if len(checked) > 1:
            self.add_alarm("Select only 1 tool to load")
        elif checked:
            ACTION.CALL_MDI("M61 Q{}".format(checked[0]))
        else:
            self.add_alarm("No tool selected")

    # alarm tab
    def btn_clear_alarms_clicked(self):
        ACTION.UPDATE_MACHINE_LOG('', 'DELETE')

    def btn_save_alarms_clicked(self):
        text = self.w.machinelog.toPlainText()
        filename = self.w.lbl_clock.text().encode('utf-8')
        filename = 'alarms_' + filename.replace(' ', '_') + '.txt'
        with open(filename, 'w') as f:
            f.write(text)

    def btn_reload_file_clicked(self):
        if self.last_loaded_program:
            self.w.progressBar.setValue(0)
            ACTION.OPEN_PROGRAM(self.last_loaded_program)

    def slow_jog_clicked(self, state):
        slider = self.w.sender().property('slider')
        current = self.w[slider].value()
        max = self.w[slider].maximum()
        if state:
            self.w.sender().setText("SLOW")
            self.w[slider].setMaximum(max / self.slow_jog_factor)
            self.w[slider].setValue(current / self.slow_jog_factor)
            self.w[slider].setPageStep(1)
        else:
            self.w.sender().setText("FAST")
            self.w[slider].setMaximum(max * self.slow_jog_factor)
            self.w[slider].setValue(current * self.slow_jog_factor)
            self.w[slider].setPageStep(1)

    #####################
    # general functions #
    #####################

    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    def editor_exit(self):
        self.btn_gcode_edit_clicked(False)

    def set_active_mode(self, mode, index):
        #print mode,index
        def update(widget):
            for key, value in self.activeWidgetDict.iteritems():
                #print mode,key,value
                if key == widget:
                    print widget
                    self.w[key].setStyleSheet('#%s%s' %
                                              (key, self.activeStyle))
                    self.activeWidgetDict[key] = True
                elif value == True:
                    print 'switch off', key
                    self.w[key].setStyleSheet('#%s%s' %
                                              (key, self.defaultStyle))
                    self.activeWidgetDict[key] = False

        if mode == 'program':
            if index == 'run':
                self.w.mainLeftStack.setCurrentIndex(0)  # gcode
                self.w.mainPaneStack.setCurrentIndex(0)  # normal
                update('programPage')
                self.w.label_mode.setText('Operation-Run Program')
            else:
                self.w.mainLeftStack.setCurrentIndex(0)  # gcode
                self.w.mainPaneStack.setCurrentIndex(1)  # load
                update('loadPage')
                self.w.label_mode.setText('Operation-Load Program')
        elif mode == 'setup':
            self.w.mainPaneStack.setCurrentIndex(0)  # normal
            self.w.widgetswitcher.setCurrentIndex(3)  # setup manual
            self.w.mainLeftStack.setCurrentIndex(1)  # setup html
            update('setupPage')
            self.w.label_mode.setText('Operation- Manual Setup')
        elif mode == 'mdi':
            self.w.mainPaneStack.setCurrentIndex(0)
            cur = self.w.widgetswitcher.currentIndex()
            if cur == 4:
                next = self.w.mdi_tab.currentIndex() + 1
                if next > self.w.mdi_tab.count() - 1:
                    next = 0
                self.w.mdi_tab.setCurrentIndex(next)
            else:
                self.w.widgetswitcher.setCurrentIndex(4)
                self.w.mdi_tab.setCurrentIndex(0)
            update('mdiPage')
            self.w.label_mode.setText('Operation- MDI Control')
        elif mode == 'offsetPage':
            self.w.mainPaneStack.setCurrentIndex(0)
            cur = self.w.widgetswitcher.currentIndex()
            if cur == 2:
                self.w.widgetswitcher.setCurrentIndex(0)
                update('tooloffsetsPage')
            else:
                self.w.widgetswitcher.setCurrentIndex(2)
                update('workoffsetsPage')
        elif mode == 'graphics':
            cur = self.w.mainLeftStack.currentIndex()
            if cur == 0:  # gcode
                if self.w.widgetswitcher.get_current_number() == 0:
                    self.w.widgetswitcher.show_default()
                    self.w.mainLeftStack.setCurrentIndex(2)
                elif self.w.widgetswitcher.get_current_number() == 1:
                    self.w.widgetswitcher.show_default()
                    self.w.mainLeftStack.setCurrentIndex(0)
            elif cur == 2:
                self.w.mainLeftStack.setCurrentIndex(0)
                self.w.widgetswitcher.show_id_widget(1)
        else:
            print('mode/index not recognized')
            return
        self.current_mode = (mode, index)

    def btn_start_macro_clicked(self):
        self.w.label_mode.setText('Operation- MDI Control')
        self.w.mditouchy.run_command()
        return

    def abort(self, state):
        if not state:
            return
        if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
            self.w.close()
        else:
            ACTION.ABORT()

    def make_progressbar(self):
        self.w.progressbBar = QtWidgets.QProgressBar()
        self.w.progressBar.setRange(0, 100)
        self.w.statusBar.addWidget(self.w.progressBar)

    def update_runtimer(self):
        if self.timerOn is False or STATUS.is_auto_paused(): return
        self.time_tenths += 1
        if self.time_tenths == 10:
            self.time_tenths = 0
            self.run_time += 1
            hours, remainder = divmod(self.run_time, 3600)
            minutes, seconds = divmod(remainder, 60)
            self.w.lbl_runtime.setText("{:02d}:{:02d}:{:02d}".format(
                hours, minutes, seconds))

    def start_timer(self):
        self.run_time = 0
        self.timerOn = True

    def stop_timer(self):
        self.timerOn = False

    def mode_changed(self, data):
        self._block_signal = True
        self.w.pushbutton_metric.setChecked(data)
        # if using state labels option update the labels
        if self.w.pushbutton_metric._state_text:
            self.w.pushbutton_metric.setText(None)
        self._block_signal = False

    def change_mode(self, data):
        if self._block_signal: return
        if data:
            ACTION.CALL_MDI('G21')
        else:
            ACTION.CALL_MDI('G20')

    def homed_on_test(self):
        return (STATUS.machine_is_on()
                and (STATUS.is_all_homed() or INFO.NO_HOME_REQUIRED))

    # file tab
    def btn_gcode_edit_clicked(self, state):
        if not STATUS.is_on_and_idle():
            return
        for x in ["load", "next", "prev"]:
            self.w["btn_file_{}".format(x)].setEnabled(not state)
        if state:
            self.w.filemanager.hide()
            self.w.gcode_editor.show()
            self.w.gcode_editor.editMode()
        else:
            self.w.filemanager.show()
            self.w.gcode_editor.hide()
            self.w.gcode_editor.readOnlyMode()

    def btn_load_file_clicked(self):
        fname = self.w.filemanager.getCurrentSelected()
        if fname[1] is True:
            self.load_code(fname[0])

    # class patched filemanager to trap single click loading
    # this makes the original function do nothing
    def FMGRnoop(self, fname):
        pass

    def load_code(self, fname):
        if fname is None: return
        if fname.endswith(".ngc") or fname.endswith(".py"):
            # call original filemanager load function to load program
            self.w.filemanager.superLoad(fname)

            # change filepath extension to autoload an html setup page
            fname = os.path.splitext(fname)[0] + '.html'

        if fname.endswith(".html"):
            if os.path.exists(fname):
                self.web_view.load(QtCore.QUrl.fromLocalFile(fname))
                return
        self.set_default_html(fname)

    def set_default_html(self, filename=None):
        if filename is None: filename = 'No program Loaded'
        print filename
        self.html = """<html>
<head>
<title>Test page for the download:// scheme</title>
</head>
<body>
<h1>Setup Tab</h1>
<p> tried loading::%s</p>
<p>If there was a HTML setup file , it would auto load and be shown here..</p>
<img src="file://%s" alt="lcnc_swoop" />
<hr />

<a href="http://linuxcnc.org/docs/html/lathe/lathe-user.html">Lathe User Information link</a>
</body>
</html>
""" % (filename, os.path.join(self.PATH.IMAGEDIR, 'lcnc_swoop.png'))
        self.web_view.setHtml(self.html)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control

    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            self.abort(state)

    def on_keycall_pause(self, event, state, shift, cntrl):
        if state and STATUS.is_auto_mode() and self.use_keyboard():
            ACTION.PAUSE()

    # dialogs
    def on_keycall_F3(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'ORIGINOFFSET'})

    def on_keycall_F4(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'CAMVIEW'})

    def on_keycall_F6(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'TOOLOFFSET'})

    def on_keycall_F7(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'VERSAPROBE'})

    def on_keycall_F9(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'Calculator'})

    def on_keycall_F11(self, event, state, shift, cntrl):
        if state:
            pass

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    ###########################
    # **** closing event **** #
    ###########################
    def closing_cleanup__(self):
        pass

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 25
0
class HandlerClass:
    def __init__(self, halcomp, widgets, paths):
        self.w = widgets
        self.PATHS = paths
        self.hal = halcomp
        INIPATH = os.environ.get('INI_FILE_NAME', '/dev/null')
        self.inifile = linuxcnc.ini(INIPATH)
        self.STYLEEDITOR = SSE(widgets,paths)
        KEYBIND.add_call('Key_F12','on_keycall_F12')
        
#        STAT.connect('general',self.return_value)
        STAT.connect('state-on', self.machine_on)
        STAT.connect('state-off', self.machine_off)
        STAT.connect('gcode-line-selected', self.gcode_line_selected)
        STAT.connect('hard-limits-tripped', self.hard_limit_tripped)
        STAT.connect("interp-idle", self.interp_idle_changed)
        STAT.connect("user-system-changed", self.user_system_changed)
        STAT.connect("tool-in-spindle-changed", self.tool_in_spindle_changed)
        STAT.connect("file-loaded", self.file_loaded)
        STAT.connect("all-homed", self.all_homed)
        STAT.connect("not-all-homed", self.not_homed)

# some global variables
        self.axis_list = INFO.AVAILABLE_AXES
        self.joint_list = INFO.AVAILABLE_JOINTS
        self.max_velocity = INFO.MAX_LINEAR_VELOCITY
        self.system_list = ["G53","G54","G55","G56","G57","G58","G59","G59.1","G59.2","G59.3"]
        self.home_location_x = self.inifile.find('JOINT_0', 'HOME')
        self.home_location_y = self.inifile.find('JOINT_1', 'HOME')
        self.home_location_z = self.inifile.find('JOINT_2', 'HOME')
        self.tool_sensor_x = self.inifile.find('TOOLSENSOR', 'X')
        self.tool_sensor_y = self.inifile.find('TOOLSENSOR', 'Y')
        self.laser_offset_x = self.inifile.find('LASER', 'X')
        self.laser_offset_y = self.inifile.find('LASER', 'Y')
        self.homed = False
        self.start_line = 0
        self.program_length = 0
        self.slow_jog_factor = 10
        self.tool_in_spindle = 0
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.onoff_list = ["widget_controls", "Program_frame", "DRO_frame"]

    def initialized__(self):
        self.init_pins()
        self.init_preferences()
        self.init_widgets()
        self.init_locations()

    # initialize DRO style
        for i in map(str.lower, self.axis_list):
            self.w["dro_axis_{}".format(i)].setStyle(self.w["dro_axis_{}".format(i)].style())

    #############################
    # SPECIAL FUNCTIONS SECTION #
    #############################
    def init_pins(self):
        # these pins are needed so that the touchoff subroutine can read the variables
        self.hal.newpin("touch_height", hal.HAL_FLOAT, hal.HAL_OUT)
        self.hal.newpin("sensor_height", hal.HAL_FLOAT, hal.HAL_OUT)
        self.hal.newpin("zero_height", hal.HAL_FLOAT, hal.HAL_OUT)
        self.hal.newpin("search_vel", hal.HAL_FLOAT, hal.HAL_OUT)
        self.hal.newpin("probe_vel", hal.HAL_FLOAT, hal.HAL_OUT)
        self.hal.newpin("max_probe", hal.HAL_FLOAT, hal.HAL_OUT)
        
    def init_preferences(self):
        if self.w.PREFS_:
            self.reload_tool = self.w.PREFS_.getpref('Tool to load', 0, int,'CUSTOM_FORM_ENTRIES')
            self.last_loaded_program = self.w.PREFS_.getpref('last_file_path', None, str,'BOOK_KEEPING')
            temp1 = self.w.PREFS_.getpref('Reload program', False, bool,'CUSTOM_FORM_ENTRIES')
            temp2 = self.w.PREFS_.getpref('Reload tool', False, bool,'CUSTOM_FORM_ENTRIES')
            temp3 = self.w.PREFS_.getpref('Tool sensor', False, bool,'CUSTOM_FORM_ENTRIES')
        else:
            temp1 = temp2 = temp3 = False
            self.add_alarm("No preference file found")
        self.w.checkBox_reload_program.setChecked(temp1)
        self.w.checkBox_reload_tool.setChecked(temp2)
        self.w.checkBox_tool_sensor.setChecked(temp3)
        self.chk_tool_sensor(temp3)

    def init_widgets(self):
        self.w.main_tab_widget.setCurrentIndex(0)
        self.w.slider_jog.setMaximum(self.max_velocity * 60)
        self.w.slider_jog.setValue(INFO.DEFAULT_LINEAR_JOG_VEL)
        self.w.slider_maxv.setMaximum(self.max_velocity * 60)
        self.w.slider_maxv.setValue(self.max_velocity * 60)
        self.w.slider_feed.setMaximum(INFO.MAX_FEED_OVERRIDE)
        self.w.slider_feed.setValue(100)
        self.w.slider_rapid.setMaximum(100)
        self.w.slider_rapid.setValue(100)
        self.w.slider_spindle.setMinimum(INFO.MIN_SPINDLE_OVERRIDE)
        self.w.slider_spindle.setMaximum(INFO.MAX_SPINDLE_OVERRIDE)
        self.w.slider_spindle.setValue(100)
        self.w.checkBox_override_limits.setChecked(False)
        self.w.checkBox_override_limits.setEnabled(False)
        self.w.filemanager.show()
        self.w.gcode_editor.hide()
        self.w.btn_from_line.setEnabled(False)
       
    def init_locations(self):
        touch_height = self.inifile.find('TOOLSENSOR', 'TOUCH_HEIGHT') or "50"
        sensor_height = self.inifile.find('TOOLSENSOR', 'SENSOR_HEIGHT') or "50"
        max_probe = self.inifile.find('TOOLSENSOR', 'MAXPROBE') or "40"
        search_vel = self.inifile.find('TOOLSENSOR', 'SEARCH_VEL') or "200"
        probe_vel = self.inifile.find('TOOLSENSOR', 'PROBE_VEL') or "50"
        self.w.lbl_maxv.setText(str(self.max_velocity * 60))
        self.w.lbl_touch_height.setText(touch_height)
        self.w.lbl_sensor_height.setText(sensor_height)
        self.w.lbl_maxprobe.setText(max_probe)
        self.w.lbl_search_vel.setText(search_vel)
        self.w.lbl_probe_vel.setText(probe_vel)
        self.hal['touch_height'] = touch_height
        self.hal['sensor_height'] = sensor_height
        self.hal['max_probe'] = max_probe
        self.hal['search_vel'] = search_vel
        self.hal['probe_vel'] = probe_vel
        # home location
        if not self.home_location_x or not self.home_location_y or not self.home_location_z:
            self.w.btn_go_home.setEnabled(False)
            self.w.groupBox_home.hide()
            self.w.lbl_no_home.show()
            self.add_alarm("No valid home location found")
        else:
            self.w.lbl_home_x.setText(self.home_location_x)
            self.w.lbl_home_y.setText(self.home_location_y)
            self.w.lbl_no_home.hide()
        # laser offsets
        if not self.laser_offset_x or not self.laser_offset_y:
            self.w.btn_ref_laser.setEnabled(False)
            self.w.btn_laser_on.setEnabled(False)
            self.w.groupBox_laser.hide()
            self.w.lbl_no_laser_offsets.show()
            self.add_alarm("No valid laser offsets found")
        else:
            self.w.lbl_laser_x.setText(self.laser_offset_x)
            self.w.lbl_laser_y.setText(self.laser_offset_y)
            self.w.lbl_no_laser_offsets.hide()
        # tool sensor location
        if not self.tool_sensor_x or not self.tool_sensor_y:
            self.w.chk_tool_sensor.hide()
            self.w.btn_go_g30.setEnabled(False)
            self.w.groupBox_sensor.hide()
            self.w.lbl_no_toolsensor.show()
            self.add_alarm("No valid tool sensor location found")
        else:
            self.w.lbl_sensor_x.setText(self.tool_sensor_x)
            self.w.lbl_sensor_y.setText(self.tool_sensor_y)
            self.w.lbl_no_toolsensor.hide()

    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2):
#                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F4,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, QtWidgets.QLineEdit):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                if isinstance(receiver2, TOOL_TABLE):
                    flag = True
                    break
                if isinstance(receiver2, OFFSET_VIEW):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STAT.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self,event,is_pressed,shift,cntrl)
        except NameError as e:
            self.add_alarm('Exception in KEYBINDING: {}'.format (e))
        except Exception as e:
            LOG.error('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s'%(KEYBIND.convert(event),key)
            return False

    #########################
    # CALLBACKS FROM STATUS #
    #########################
    def machine_on(self, obj):
        for widget in self.onoff_list:
            self.w[widget].setEnabled(True)

    def machine_off(self, obj):
        for widget in self.onoff_list:
            self.w[widget].setEnabled(False)

    def gcode_line_selected(self, obj, data):
        if self.w.btn_from_line.isChecked():
            self.start_line = data
            self.w.btn_start.setText("START FROM {}".format(data))

    def interp_idle_changed(self, obj):
        self.start_line = 0
        self.w.btn_start.setText("START FROM 0")
        
    def user_system_changed(self, obj, data):
        sys = self.system_list[int(data)]
        self.w.actionbutton_rel.setText(sys)

    def tool_in_spindle_changed(self, obj, data):
        self.tool_in_spindle = data

    def file_loaded(self, obj, filename):
        if filename is not None:
            self.w.progressBar.setValue(0)
            self.last_loaded_program = filename
            fileobject = file(filename, 'r')
            lines = fileobject.readlines()
            fileobject.close()
            self.program_length = len(lines)
            self.start_line = 0
            self.w.btn_from_line.setEnabled(True)
            self.w.btn_start.setText("START FROM 0")
        else:
            self.w.btn_from_line.setEnabled(False)
            self.add_alarm("Filename not valid")

    def all_homed(self, obj):
        self.homed = True
        self.w.actionbutton_view_p.click()
        for i in map(str.lower, self.axis_list):
            self.w["dro_axis_{}".format(i)].setProperty('homed', True)
            self.w["dro_axis_{}".format(i)].setStyle(self.w["dro_axis_{}".format(i)].style())
        if self.tool_in_spindle == 0 and self.w.checkBox_reload_tool.checkState():
            command = "M61 Q{}".format(self.reload_tool)
            ACTION.CALL_MDI_WAIT(command)
        if self.last_loaded_program and self.w.checkBox_reload_program.checkState():
            ACTION.OPEN_PROGRAM(self.last_loaded_program)
            self.w.filemanager.updateDirectoryView(self.last_loaded_program)

    def not_homed(self, obj, data):
        self.homed = False
        for i in map(str.lower, self.axis_list):
            self.w["dro_axis_{}".format(i)].setProperty('homed', False)
            self.w["dro_axis_{}".format(i)].setStyle(self.w["dro_axis_{}".format(i)].style())

    def hard_limit_tripped(self, obj, tripped, list_of_tripped):
        self.w.checkBox_override_limits.setEnabled(tripped)
        if not tripped:
            self.w.checkBox_override_limits.setChecked(False)
    
    #######################
    # CALLBACKS FROM FORM #
    #######################
    # program frame
    def btn_start_clicked(self):
        if not STAT.is_auto_mode():
            return
        self.w.btn_from_line.setChecked(False)
        self.add_alarm("Started program from line {}".format(self.start_line))
        ACTION.RUN(self.start_line)

    def btn_reload_file_clicked(self):
        if self.last_loaded_program:
            self.w.progressBar.setValue(0)
            ACTION.OPEN_PROGRAM(self.last_loaded_program)

    # tool frame
    def btn_go_home_clicked(self):
        ACTION.CALL_MDI_WAIT("G53 G0 Z0")
        command = "G53 G0 X{} Y{}".format(self.w.lbl_home_x.text(), self.w.lbl_home_y.text())
        ACTION.CALL_MDI_WAIT(command)

    def btn_go_g30_clicked(self):
        ACTION.CALL_MDI_WAIT("G53 G0 Z0")
        command = "G53 G0 X{} Y{}".format(self.w.lbl_sensor_x.text(), self.w.lbl_sensor_y.text())
        ACTION.CALL_MDI_WAIT(command)

    def btn_ref_laser_clicked(self):
        command = "G10 L20 P0 X{} Y{}".format(self.w.lbl_laser_x.text(), self.w.lbl_laser_y.text())
        ACTION.CALL_MDI_WAIT(command)

    def btn_from_line_clicked(self, state):
        if state is False:
            self.start_line = 0
            self.w.btn_start.setText("START FROM 0")

    def btn_touchoff_clicked(self):
        code = None
        if self.tool_in_spindle == 0:
            self.add_alarm("Cannot probe with no tool loaded")
            return
        if self.w.btn_touchoff.text() == "TOOL\nSENSOR":
            self.hal['zero_height'] = self.w.lineEdit_zero_height.text().encode('utf-8')
            code = "o< tool_sensor > call"
        elif self.w.btn_touchoff.text() == "TOUCH\nPLATE":
            code = "o< touch_plate > call"
        if not code is None:
            ACTION.CALL_OWORD(code)
            STAT.emit('forced-update')

    # override frame
    def btn_slow_clicked(self, state):
        if state:
            current = self.w.slider_jog.value()
            self.w.btn_slow.setText("SLOW")
            self.w.slider_jog.setMaximum(self.max_velocity * 60 / self.slow_jog_factor)
            self.w.slider_jog.setValue(current / self.slow_jog_factor)
        else:
            current = self.w.slider_jog.value()
            self.w.btn_slow.setText("FAST")
            self.w.slider_jog.setMaximum(self.max_velocity * 60)
            self.w.slider_jog.setValue(current * self.slow_jog_factor)

    def btn_maxv_max_clicked(self):
        self.w.slider_maxv.setValue(self.max_velocity * 60)

    # file tab
    def btn_gcode_edit_clicked(self, state):
        if not STAT.is_on_and_idle():
            return
        for x in ["load", "next", "prev"]:
            self.w["btn_file_{}".format(x)].setEnabled(not state)
        if state:
            self.w.filemanager.hide()
            self.w.gcode_editor.show()
            self.w.gcode_editor.editMode()
        else:
            self.w.filemanager.show()
            self.w.gcode_editor.hide()
            self.w.gcode_editor.readOnlyMode()

    # tool tab
    def btn_m61_clicked(self):
        checked = self.w.tooloffsetview.get_checked_list()
        if len(checked) > 1:
            self.add_alarm("Select only 1 tool to load")
        elif checked:
            ACTION.CALL_MDI_WAIT("M61 Q{}".format(checked[0]))
        else:
            self.add_alarm("No tool selected")

    # alarm tab
    def btn_clear_alarms_clicked(self):
        STAT.emit('update-machine-log', None, 'DELETE')

    def btn_save_alarms_clicked(self):
        text = self.w.machinelog.toPlainText()
        filename = self.w.lbl_clock.text().encode('utf-8')
        filename = 'alarms_' + filename.replace(' ','_') + '.txt'
        with open(filename, 'w') as f:
            f.write(text)

    # settings tab
    def chk_tool_sensor(self, state):
        if state:
            self.w.btn_touchoff.setText("TOOL\nSENSOR")
        else:
            self.w.btn_touchoff.setText("TOUCH\nPLATE")

    def chk_override_limits(self, state):
        if state:
            print("Override limits set")
            ACTION.SET_LIMITS_OVERRIDE()
        else:
            print("Override limits not set")
        
    #####################
    # GENERAL FUNCTIONS #
    #####################

    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STAT.is_man_mode() or not STAT.machine_is_on():
            return
        if linear:
            distance = STAT.get_jog_increment()
            rate = STAT.get_jograte()/60
        else:
            distance = STAT.get_jog_increment_angular()
            rate = STAT.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    def add_alarm(self, message):
        STAT.emit('update-machine-log', message, 'TIME')

    def alarm_added(self):
        self.w.led_alarm.setState(True)

    def tab_changed(self, index):
        self.w.btn_gcode_edit.setChecked(False)
        self.btn_gcode_edit_clicked(False)
        if index == 4:
            self.w.led_alarm.setState(False)

    #####################
    # KEY BINDING CALLS #
    #####################

    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(True)

    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(False)

    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            ACTION.ABORT()

    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state and self.homed is False:
            ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_XPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, -1, shift)
    
    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################
# items to save in preference file
    def closing_cleanup__(self):
        if self.w.PREFS_:
            self.w.PREFS_.putpref('Reload program', self.w.checkBox_reload_program.checkState(), bool, 'CUSTOM_FORM_ENTRIES')
            self.w.PREFS_.putpref('Tool to load', self.tool_in_spindle, int, 'CUSTOM_FORM_ENTRIES')
            self.w.PREFS_.putpref('Reload tool', self.w.checkBox_reload_tool.checkState(), bool, 'CUSTOM_FORM_ENTRIES')
            self.w.PREFS_.putpref('Tool sensor', self.w.checkBox_tool_sensor.checkState(), bool, 'CUSTOM_FORM_ENTRIES')

    ##############################
    # required class boiler code #
    ##############################
    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 26
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp,widgets,paths):
        self.hal = halcomp
        self.w = widgets
        self.PATH = paths
        self._big_view = -1
        self.STYLEEDITOR = SSE(widgets,paths)

    ##########################################
    # Special Functions called from QTVCP
    ##########################################

    # For changing functions in widgets we can 'class patch'.
    # class patching must be done before the class is instantiated.
    # 
    def class_patch__(self):
        GCODE.exitCall = self.editor_exit

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        STATUS.emit('play-alert','SPEAK This is a test screen for Qt V C P')
        KEYBIND.add_call('Key_F3','on_keycall_F3')
        KEYBIND.add_call('Key_F4','on_keycall_F4')
        KEYBIND.add_call('Key_F5','on_keycall_F5')
        KEYBIND.add_call('Key_F6','on_keycall_F6')
        KEYBIND.add_call('Key_F7','on_keycall_F7')
        KEYBIND.add_call('Key_F12','on_keycall_F12')
        self.w.toolOffsetDialog_._geometry_string='0 0 600 400 onwindow '

    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2,
                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F5,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self,event,is_pressed,shift,cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format (e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s'%(KEYBIND.convert(event),key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    #######################
    # callbacks from form #
    #######################
    def widget_switch(self,data):
        self.w.widgetswitcher.show_next()

    def set_edit_mode(self, num):
        if num == 2:
            self.w.gcodeeditor.editMode()
        else:
            self.w.gcodeeditor.readOnlyMode()

    #####################
    # general functions #
    #####################

    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte()/60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    # called from 'machine on' button's python command in designer
    # to test that function
    def test_function(self, text=None):
        print text

    def editor_exit(self):
        self.w.gcodeeditor.exit()

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())
    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())
    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)
    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                ACTION.ABORT()

    # dialogs
    def on_keycall_F3(self,event,state,shift,cntrl):
        if state:
            STATUS.emit('dialog-request',{'NAME':'ORIGINOFFSET'})
    def on_keycall_F4(self,event,state,shift,cntrl):
        if state:
            STATUS.emit('dialog-request',{'NAME':'CAMVIEW'})
    def on_keycall_F5(self,event,state,shift,cntrl):
        if state:
            STATUS.emit('dialog-request',{'NAME':'MACROTAB'})
    def on_keycall_F6(self,event,state,shift,cntrl):
        if state:
            STATUS.emit('dialog-request',{'NAME':'TOOLOFFSET'})
    def on_keycall_F7(self,event,state,shift,cntrl):
        if state:
            STATUS.emit('dialog-request',{'NAME':'VERSAPROBE'})
    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()


    # Linear Jogging
    def on_keycall_XPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    ###########################
    # **** closing event **** #
    ###########################
    def closing_cleanup__(self):
        pass

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)
    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 27
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        self.hal = halcomp
        self.w = widgets
        self.PATH = paths
        self._big_view = -1
        self.STYLEEDITOR = SSE(widgets, paths)

    ##########################################
    # Special Functions called from QTVCP
    ##########################################

    # For changing functions in widgets we can 'class patch'.
    # class patching must be done before the class is instantiated.
    #
    def class_patch__(self):
        GCODE.exitCall = self.editor_exit

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        STATUS.emit('play-sound', 'SPEAK This is a test screen for Qt V C P')
        KEYBIND.add_call('Key_F3', 'on_keycall_F3')
        KEYBIND.add_call('Key_F4', 'on_keycall_F4')
        KEYBIND.add_call('Key_F5', 'on_keycall_F5')
        KEYBIND.add_call('Key_F6', 'on_keycall_F6')
        KEYBIND.add_call('Key_F7', 'on_keycall_F7')
        KEYBIND.add_call('Key_F8', 'on_keycall_F8')
        KEYBIND.add_call('Key_F9', 'on_keycall_custom', 'f9 pressed tesst')
        KEYBIND.add_call('Key_F10', 'on_keycall_custom', 'f10 pressed tesst')
        KEYBIND.add_call('Key_F11', 'on_keycall_custom', 'f11 pressed test')
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')

        self.w.toolOffsetDialog_._geometry_string = '0 0 600 400 onwindow '

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F6, QtCore.Qt.Key_F7, QtCore.Qt.Key_F8,
                        QtCore.Qt.Key_F12):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    #######################
    # callbacks from form #
    #######################
    def widget_switch(self, data):
        self.w.widgetswitcher.show_next()

    def set_edit_mode(self, num):
        if num == 2:
            self.w.gcodeeditor.editMode()
        else:
            self.w.gcodeeditor.readOnlyMode()

    #####################
    # general functions #
    #####################

    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    # called from 'machine on' button's python command in designer
    # to test that function
    def test_function(self, text=None):
        print text

    def editor_exit(self):
        self.w.gcodeeditor.exit()

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                ACTION.ABORT()

    # dialogs
    def on_keycall_F3(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'ORIGINOFFSET'})

    def on_keycall_F4(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {
                'NAME': 'CAMVIEW',
                'NONBLOCKING': True
            })

    def on_keycall_F5(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'MACROTAB'})

    def on_keycall_F6(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'TOOLOFFSET'})

    def on_keycall_F7(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {'NAME': 'VERSAPROBE'})

    def on_keycall_F8(self, event, state, shift, cntrl):
        if state:
            STATUS.emit('dialog-request', {
                'NAME': 'MACHINELOG',
                'NONBLOCKING': True
            })

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    # f9, f10 and f11 call this function with different values
    def on_keycall_custom(self, event, state, shift, cntrl, value):
        if state:
            print 'custom keycall function value: ', value

    ###########################
    # **** closing event **** #
    ###########################
    def closing_cleanup__(self):
        pass

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 28
0
class HandlerClass:
    def __init__(self, halcomp, widgets, paths):
        self.h = halcomp
        self.w = widgets
        self.gcodes = GCodes(widgets)
        self.valid = QtGui.QDoubleValidator(-999.999, 999.999, 3)
        self.styleeditor = SSE(widgets, paths)
        KEYBIND.add_call('Key_F4', 'on_keycall_F4')
        KEYBIND.add_call('Key_F12','on_keycall_F12')
        KEYBIND.add_call('Key_Pause', 'on_keycall_PAUSE')
        KEYBIND.add_call('Key_Space', 'on_keycall_PAUSE')
        # some global variables
        self.factor = 1.0
        self.probe = None
        self.default_setup = os.path.join(PATH.CONFIGPATH, "default_setup.html")
        self.docs = os.path.join(PATH.SCREENDIR, PATH.BASEPATH,'docs/getting_started.html')
        self.start_line = 0
        self.run_time = 0
        self.time_tenths = 0
        self.timer_on = False
        self.home_all = False
        self.min_spindle_rpm = INFO.MIN_SPINDLE_SPEED
        self.max_spindle_rpm = INFO.MAX_SPINDLE_SPEED
        self.max_spindle_power = INFO.get_error_safe_setting('DISPLAY', 'MAX_SPINDLE_POWER',"0")
        self.max_linear_velocity = INFO.MAX_TRAJ_VELOCITY
        self.system_list = ["G54","G55","G56","G57","G58","G59","G59.1","G59.2","G59.3"]
        self.slow_jog_factor = 10
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.first_turnon = True
        self.unit_label_list = ["ts_height", "tp_height", "zoffset_units", "max_probe_units"]
        self.lineedit_list = ["work_height", "touch_height", "sensor_height", "laser_x", "laser_y",
                              "sensor_x", "sensor_y", "camera_x", "camera_y",
                              "search_vel", "probe_vel", "max_probe", "eoffset_count"]
        self.onoff_list = ["frame_program", "frame_tool", "frame_offsets", "frame_dro", "frame_override"]
        self.axis_a_list = ["label_axis_a", "dro_axis_a", "action_zero_a", "axistoolbutton_a",
                            "action_home_a", "widget_jog_angular", "widget_increments_angular",
                            "a_plus_jogbutton", "a_minus_jogbutton"]

        STATUS.connect('general', self.dialog_return)
        STATUS.connect('state-on', lambda w: self.enable_onoff(True))
        STATUS.connect('state-off', lambda w: self.enable_onoff(False))
        STATUS.connect('mode-auto', lambda w: self.enable_auto(True))
        STATUS.connect('gcode-line-selected', lambda w, line: self.set_start_line(line))
        STATUS.connect('hard-limits-tripped', self.hard_limit_tripped)
        STATUS.connect('program-pause-changed', lambda w, state: self.w.btn_pause_spindle.setEnabled(state))
        STATUS.connect('user-system-changed', lambda w, data: self.user_system_changed(data))
        STATUS.connect('metric-mode-changed', lambda w, mode: self.metric_mode_changed(mode))
        STATUS.connect('file-loaded', self.file_loaded)
        STATUS.connect('all-homed', self.all_homed)
        STATUS.connect('not-all-homed', self.not_all_homed)
        STATUS.connect('periodic', lambda w: self.update_runtimer())
        STATUS.connect('interp-idle', lambda w: self.stop_timer())
        STATUS.connect('actual-spindle-speed-changed',self.update_spindle)
        STATUS.connect('requested-spindle-speed-changed',self.update_spindle_requested)
        STATUS.connect('override-limits-changed', lambda w, state, data: self._check_override_limits(state, data))

        self.html = """<html>
<head>
<title>Test page for the download:// scheme</title>
</head>
<body>
<h1>Setup Tab</h1>
<p>If you select a file with .html as a file ending, it will be shown here..</p>
<img src="file://%s" alt="lcnc_swoop" />
<hr />
</body>
</html>
""" %(os.path.join(paths.IMAGEDIR,'lcnc_swoop.png'))


    def class_patch__(self):
        self.old_fman = FM.load
        FM.load = self.load_code

    def initialized__(self):
        self.init_pins()
        self.init_preferences()
        self.init_widgets()
        self.init_probe()
        self.init_utils()
        self.w.stackedWidget_log.setCurrentIndex(0)
        self.w.stackedWidget_dro.setCurrentIndex(0)
        if self.probe is not None:
            self.probe.hide()
        self.w.btn_pause_spindle.setEnabled(False)
        self.w.btn_dimensions.setChecked(True)
        self.w.page_buttonGroup.buttonClicked.connect(self.main_tab_changed)
        self.w.filemanager.onUserClicked()    
        self.w.filemanager_usb.onMediaClicked()

    # hide widgets for A axis if not present
        if "A" not in INFO.AVAILABLE_AXES:
            for i in self.axis_a_list:
                self.w[i].hide()
            self.w.lbl_increments_linear.setText("INCREMENTS")
    # set validators for lineEdit widgets
        for val in self.lineedit_list:
            self.w['lineEdit_' + val].setValidator(self.valid)
    # set unit labels according to machine mode
        unit = "MM" if INFO.MACHINE_IS_METRIC else "IN"
        for i in self.unit_label_list:
            self.w['lbl_' + i].setText(unit)
        unit = "MM/MIN" if INFO.MACHINE_IS_METRIC else "IN/MIN"
        for i in ["search_vel_units", "probe_vel_units", "jog_linear"]:
            self.w['lbl_' + i].setText(unit)
        self.w.setWindowFlags(QtCore.Qt.FramelessWindowHint)

    #############################
    # SPECIAL FUNCTIONS SECTION #
    #############################
    def init_pins(self):
        # spindle control pins
        pin = self.h.newpin("spindle_amps", hal.HAL_FLOAT, hal.HAL_IN)
        pin.value_changed.connect(self.spindle_pwr_changed)
        pin = self.h.newpin("spindle_volts", hal.HAL_FLOAT, hal.HAL_IN)
        pin.value_changed.connect(self.spindle_pwr_changed)
        pin = self.h.newpin("spindle_fault", hal.HAL_U32, hal.HAL_IN)
        pin.value_changed.connect(self.spindle_fault_changed)
#        self.h.newpin("spindle_at_speed", hal.HAL_BIT, hal.HAL_IN)
        pin = self.h.newpin("modbus-errors", hal.HAL_U32, hal.HAL_IN)
        pin.value_changed.connect(self.mb_errors_changed)
        self.h.newpin("spindle_inhibit", hal.HAL_BIT, hal.HAL_OUT)
        # external offset control pins
        self.h.newpin("eoffset_enable", hal.HAL_BIT, hal.HAL_OUT)
        self.h.newpin("eoffset_clear", hal.HAL_BIT, hal.HAL_OUT)
        self.h.newpin("eoffset_count", hal.HAL_S32, hal.HAL_OUT)
        pin = self.h.newpin("eoffset_value", hal.HAL_FLOAT, hal.HAL_IN)
        pin.value_changed.connect(self.eoffset_changed)

    def init_preferences(self):
        if not self.w.PREFS_:
            self.add_status("CRITICAL - no preference file found, enable preferences in screenoptions widget")
            return
        self.last_loaded_program = self.w.PREFS_.getpref('last_loaded_file', None, str,'BOOK_KEEPING')
        self.reload_tool = self.w.PREFS_.getpref('Tool to load', 0, int,'CUSTOM_FORM_ENTRIES')
        self.w.lineEdit_laser_x.setText(str(self.w.PREFS_.getpref('Laser X', 100, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_laser_y.setText(str(self.w.PREFS_.getpref('Laser Y', -20, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_sensor_x.setText(str(self.w.PREFS_.getpref('Sensor X', 10, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_sensor_y.setText(str(self.w.PREFS_.getpref('Sensor Y', 10, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_camera_x.setText(str(self.w.PREFS_.getpref('Camera X', 10, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_camera_y.setText(str(self.w.PREFS_.getpref('Camera Y', 10, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_work_height.setText(str(self.w.PREFS_.getpref('Work Height', 20, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_touch_height.setText(str(self.w.PREFS_.getpref('Touch Height', 40, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_sensor_height.setText(str(self.w.PREFS_.getpref('Sensor Height', 40, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_search_vel.setText(str(self.w.PREFS_.getpref('Search Velocity', 40, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_probe_vel.setText(str(self.w.PREFS_.getpref('Probe Velocity', 10, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_max_probe.setText(str(self.w.PREFS_.getpref('Max Probe', 10, float, 'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_eoffset_count.setText(str(self.w.PREFS_.getpref('Eoffset count', 0, int, 'CUSTOM_FORM_ENTRIES')))
        self.w.chk_eoffsets.setChecked(self.w.PREFS_.getpref('External offsets', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_reload_program.setChecked(self.w.PREFS_.getpref('Reload program', False, bool,'CUSTOM_FORM_ENTRIES'))
        self.w.chk_reload_tool.setChecked(self.w.PREFS_.getpref('Reload tool', False, bool,'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_keyboard.setChecked(self.w.PREFS_.getpref('Use keyboard', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_tool_sensor.setChecked(self.w.PREFS_.getpref('Use tool sensor', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_touchplate.setChecked(self.w.PREFS_.getpref('Use tool touchplate', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_run_from_line.setChecked(self.w.PREFS_.getpref('Run from line', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_virtual.setChecked(self.w.PREFS_.getpref('Use virtual keyboard', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_camera.setChecked(self.w.PREFS_.getpref('Use camera', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_alpha_mode.setChecked(self.w.PREFS_.getpref('Use alpha display mode', False, bool, 'CUSTOM_FORM_ENTRIES'))
        self.w.chk_inhibit_selection.setChecked(self.w.PREFS_.getpref('Inhibit display mouse selection', True, bool, 'CUSTOM_FORM_ENTRIES'))

    def closing_cleanup__(self):
        if not self.w.PREFS_: return
        if self.last_loaded_program is not None:
            self.w.PREFS_.putpref('last_loaded_directory', os.path.dirname(self.last_loaded_program), str, 'BOOK_KEEPING')
            self.w.PREFS_.putpref('last_loaded_file', self.last_loaded_program, str, 'BOOK_KEEPING')
        self.w.PREFS_.putpref('Tool to load', STATUS.get_current_tool(), int, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Laser X', self.w.lineEdit_laser_x.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Laser Y', self.w.lineEdit_laser_y.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Sensor X', self.w.lineEdit_sensor_x.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Sensor Y', self.w.lineEdit_sensor_y.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Camera X', self.w.lineEdit_camera_x.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Camera Y', self.w.lineEdit_camera_y.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Work Height', self.w.lineEdit_work_height.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Touch Height', self.w.lineEdit_touch_height.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Sensor Height', self.w.lineEdit_sensor_height.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Search Velocity', self.w.lineEdit_search_vel.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Probe Velocity', self.w.lineEdit_probe_vel.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Max Probe', self.w.lineEdit_max_probe.text().encode('utf-8'), float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Eoffset count', self.w.lineEdit_eoffset_count.text().encode('utf-8'), int, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('External offsets', self.w.chk_eoffsets.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Reload program', self.w.chk_reload_program.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Reload tool', self.w.chk_reload_tool.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use keyboard', self.w.chk_use_keyboard.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use tool sensor', self.w.chk_use_tool_sensor.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use tool touchplate', self.w.chk_use_touchplate.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Run from line', self.w.chk_run_from_line.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use virtual keyboard', self.w.chk_use_virtual.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use camera', self.w.chk_use_camera.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use alpha display mode', self.w.chk_alpha_mode.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Inhibit display mouse selection', self.w.chk_inhibit_selection.isChecked(), bool, 'CUSTOM_FORM_ENTRIES')
        if self.probe is not None:
            self.probe.closing_cleanup__()

    def init_widgets(self):
        self.w.main_tab_widget.setCurrentIndex(0)
        self.w.slider_jog_linear.setMaximum(INFO.MAX_LINEAR_JOG_VEL)
        self.w.slider_jog_linear.setValue(INFO.DEFAULT_LINEAR_JOG_VEL)
        self.w.slider_jog_angular.setMaximum(INFO.MAX_ANGULAR_JOG_VEL)
        self.w.slider_jog_angular.setValue(INFO.DEFAULT_ANGULAR_JOG_VEL)
        self.w.slider_feed_ovr.setMaximum(INFO.MAX_FEED_OVERRIDE)
        self.w.slider_feed_ovr.setValue(100)
        self.w.slider_spindle_ovr.setMinimum(INFO.MIN_SPINDLE_OVERRIDE)
        self.w.slider_spindle_ovr.setMaximum(INFO.MAX_SPINDLE_OVERRIDE)
        self.w.slider_spindle_ovr.setValue(100)
        self.w.chk_override_limits.setChecked(False)
        self.w.chk_override_limits.setEnabled(False)
        self.w.lbl_maxv_percent.setText("100 %")
        self.w.lbl_max_rapid.setText(str(self.max_linear_velocity))
        self.w.lbl_home_x.setText(INFO.get_error_safe_setting('JOINT_0', 'HOME',"50"))
        self.w.lbl_home_y.setText(INFO.get_error_safe_setting('JOINT_1', 'HOME',"50"))
        self.w.cmb_gcode_history.addItem("No File Loaded")
        self.w.cmb_gcode_history.wheelEvent = lambda event: None
        self.w.jogincrements_linear.wheelEvent = lambda event: None
        self.w.jogincrements_angular.wheelEvent = lambda event: None
        self.w.gcode_editor.hide()
        self.w.filemanager.table.setShowGrid(False)
        self.w.filemanager_usb.table.setShowGrid(False)
        self.w.tooloffsetview.setShowGrid(False)
        self.w.offset_table.setShowGrid(False)
        self.w.divider_line.hide()
        # move clock to statusbar
        self.w.statusbar.addPermanentWidget(self.w.lbl_clock)
        #set up gcode list
        self.gcodes.setup_list()

        # check for default setup html file
        try:
            # web view widget for SETUP page
            if self.w.web_view:
                self.toolBar = QtWidgets.QToolBar(self.w)
                self.w.layout_setup.addWidget(self.toolBar)

                self.backBtn = QtWidgets.QPushButton(self.w)
                self.backBtn.setEnabled(True)
                self.backBtn.setIcon(QtGui.QIcon(':/qt-project.org/styles/commonstyle/images/left-32.png'))
                self.backBtn.clicked.connect(self.back)
                self.toolBar.addWidget(self.backBtn)

                self.forBtn = QtWidgets.QPushButton(self.w)
                self.forBtn.setEnabled(True)
                self.forBtn.setIcon(QtGui.QIcon(':/qt-project.org/styles/commonstyle/images/right-32.png'))
                self.forBtn.clicked.connect(self.forward)
                self.toolBar.addWidget(self.forBtn)

                self.writeBtn = QtWidgets.QPushButton('SetUp\n Writer',self.w)
                self.writeBtn.setEnabled(True)
                self.writeBtn.clicked.connect(self.writer)
                self.toolBar.addWidget(self.writeBtn)

                self.w.layout_setup.addWidget(self.w.web_view)
                if os.path.exists(self.default_setup):
                    self.w.web_view.load(QtCore.QUrl.fromLocalFile(self.default_setup))
                else:
                    self.w.web_view.setHtml(self.html)
        except Exception as e:
            print("No default setup file found - {}".format(e))
        # set up spindle gauge
        self.w.gauge_spindle.set_max_value(self.max_spindle_rpm)
        self.w.gauge_spindle.set_max_reading(self.max_spindle_rpm / 1000)
        self.w.gauge_spindle.set_threshold(self.min_spindle_rpm)
        self.w.gauge_spindle.set_label("RPM")
        
    def init_probe(self):
        probe = INFO.get_error_safe_setting('PROBE', 'USE_PROBE', 'none').lower()
        if probe == 'versaprobe':
            LOG.info("Using Versa Probe")
            from qtvcp.widgets.versa_probe import VersaProbe
            self.probe = VersaProbe()
            self.probe.setObjectName('versaprobe')
        elif probe == 'basicprobe':
            LOG.info("Using Basic Probe")
            from qtvcp.widgets.basic_probe import BasicProbe
            self.probe = BasicProbe()
            self.probe.setObjectName('basicprobe')
        else:
            LOG.info("No valid probe widget specified")
            self.w.btn_probe.hide()
            return
        self.w.probe_layout.addWidget(self.probe)
        self.probe.hal_init()

    def init_utils(self):
        from qtvcp.lib.gcode_utility.facing import Facing
        self.facing = Facing()
        self.w.layout_facing.addWidget(self.facing)
        from qtvcp.lib.gcode_utility.hole_circle import Hole_Circle
        self.hole_circle = Hole_Circle()
        self.w.layout_hole_circle.addWidget(self.hole_circle)

    def processed_focus_event__(self, receiver, event):
        if not self.w.chk_use_virtual.isChecked() or STATUS.is_auto_mode(): return
        if isinstance(receiver, QtWidgets.QLineEdit):
            if not receiver.isReadOnly():
                self.w.stackedWidget_dro.setCurrentIndex(1)
        elif isinstance(receiver, QtWidgets.QTableView):
            self.w.stackedWidget_dro.setCurrentIndex(1)
        elif isinstance(receiver, QtWidgets.QCommonStyle):
            return
    
    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2):
#                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F4,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, QtWidgets.QLineEdit):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                if isinstance(receiver2, TOOL_TABLE):
                    flag = True
                    break
                if isinstance(receiver2, OFFSET_VIEW):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual or in readonly mode do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False or not receiver2.isReadOnly():
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                if is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        if event.isAutoRepeat():return True

        # ok if we got here then try keybindings function calls
        # KEYBINDING will call functions from handler file as
        # registered by KEYBIND.add_call(KEY,FUNCTION) above
        return KEYBIND.manage_function_calls(self,event,is_pressed,key,shift,cntrl)

    #########################
    # CALLBACKS FROM STATUS #
    #########################

    def update_spindle(self,w,data):
        self.w.gauge_spindle.update_value(abs(data))

    def update_spindle_requested(self,w,data):
        self.w.gauge_spindle.set_setpoint(abs(data))

    def spindle_pwr_changed(self, data):
        # this calculation assumes the voltage is line to neutral
        # that the current reported by the VFD is total current for all 3 phases
        # and that the synchronous motor spindle has a power factor of 0.9
        try:
            power = float(self.h['spindle_volts'] * self.h['spindle_amps'] * 0.9) # V x I x PF
            pc_power = (power / float(self.max_spindle_power)) * 100
            if pc_power > 100:
                pc_power = 100
            self.w.spindle_power.setValue(int(pc_power))
        except:
            self.w.spindle_power.setValue(0)

    def spindle_fault_changed(self, data):
        fault = hex(self.h['spindle_fault'])
        self.w.lbl_spindle_fault.setText(fault)

    def mb_errors_changed(self, data):
        errors = self.h['modbus-errors']
        self.w.lbl_mb_errors.setText(str(errors))

    def eoffset_changed(self, data):
        eoffset = "{:2.3f}".format(self.h['eoffset_value'])
        self.w.lbl_eoffset_value.setText(eoffset)

    def dialog_return(self, w, message):
        rtn = message.get('RETURN')
        name = message.get('NAME')
        plate_code = bool(message.get('ID') == '_touchplate_')
        sensor_code = bool(message.get('ID') == '_toolsensor_')
        wait_code = bool(message.get('ID') == '_wait_resume_')
        unhome_code = bool(message.get('ID') == '_unhome_')
        if plate_code and name == 'MESSAGE' and rtn is True:
            self.touchoff('touchplate')
        elif sensor_code and name == 'MESSAGE' and rtn is True:
            self.touchoff('sensor')
        elif wait_code and name == 'MESSAGE':
            self.h['eoffset_clear'] = False
        elif unhome_code and name == 'MESSAGE' and rtn is True:
            ACTION.SET_MACHINE_UNHOMED(-1)

    def user_system_changed(self, data):
        sys = self.system_list[int(data) - 1]
        self.w.offset_table.selectRow(int(data) + 3)
        self.w.actionbutton_rel.setText(sys)

    def metric_mode_changed(self, mode):
        unit = "MM" if mode else "IN"
        self.w.lbl_jog_linear.setText(unit + "/MIN")
        if INFO.MACHINE_IS_METRIC == mode:
            self.factor = 1.0
            rapid = (float(self.w.slider_rapid_ovr.value()) / 100) * self.max_linear_velocity
        elif mode:
            self.factor = 25.4
            rapid = (float(self.w.slider_rapid_ovr.value()) / 100) * self.max_linear_velocity * 25.4
        else:
            self.factor = 1/25.4
            rapid = (float(self.w.slider_rapid_ovr.value()) / 100) * self.max_linear_velocity / 25.4
        self.w.lbl_max_rapid.setText("{:4.0f}".format(rapid))

    def file_loaded(self, obj, filename):
        if os.path.basename(filename).count('.') > 1:
            self.last_loaded_program = ""
            return
        if filename is not None:
            self.add_status("Loaded file {}".format(filename))
            self.w.progressBar.reset()
            self.last_loaded_program = filename
            self.w.lbl_runtime.setText("00:00:00")
        else:
            self.add_status("Filename not valid")

    def percent_loaded_changed(self, fraction):
        if fraction < 0:
            self.w.progressBar.setValue(0)
            self.w.progressBar.setFormat('PROGRESS')
        else:
            self.w.progressBar.setValue(fraction)
            self.w.progressBar.setFormat('LOADING: {}%'.format(fraction))

    def percent_done_changed(self, fraction):
        self.w.progressBar.setValue(fraction)
        if fraction < 0:
            self.w.progressBar.setValue(0)
            self.w.progressBar.setFormat('PROGRESS')
        else:
            self.w.progressBar.setFormat('COMPLETE: {}%'.format(fraction))

    def all_homed(self, obj):
        self.home_all = True
        self.w.btn_home_all.setText("ALL HOMED")
        if self.first_turnon is True:
            self.first_turnon = False
            if self.w.chk_reload_tool.isChecked():
                command = "M61 Q{}".format(self.reload_tool)
                ACTION.CALL_MDI(command)
            if self.last_loaded_program is not None and self.w.chk_reload_program.isChecked():
                if os.path.isfile(self.last_loaded_program):
                    self.w.cmb_gcode_history.addItem(self.last_loaded_program)
                    self.w.cmb_gcode_history.setCurrentIndex(self.w.cmb_gcode_history.count() - 1)
                    self.w.cmb_gcode_history.setToolTip(fname)
                    ACTION.OPEN_PROGRAM(self.last_loaded_program)
        ACTION.SET_MANUAL_MODE()
        self.w.manual_mode_button.setChecked(True)

    def not_all_homed(self, obj, list):
        self.home_all = False
        self.w.btn_home_all.setText("HOME ALL")

    def hard_limit_tripped(self, obj, tripped, list_of_tripped):
        self.add_status("Hard limits tripped")
        self.w.chk_override_limits.setEnabled(tripped)
        if not tripped:
            self.w.chk_override_limits.setChecked(False)

    # keep check button in synch of external changes
    def _check_override_limits(self,state,data):
        if 0 in data:
            self.w.chk_override_limits.setChecked(False)
        else:
            self.w.chk_override_limits.setChecked(True)

    #######################
    # CALLBACKS FROM FORM #
    #######################

    # main button bar
    def main_tab_changed(self, btn):
        index = btn.property("index")
        if index is None: return
        # if in automode still allow settings to show so override linits can be used
        if STATUS.is_auto_mode() and index != 8:
            self.add_status("Cannot switch pages while in AUTO mode")
            # make sure main page is showing
            self.w.main_tab_widget.setCurrentIndex(0)
            self.w.btn_main.setChecked(True)
            return
        if index == TAB_MAIN:
            self.w.stackedWidget_dro.setCurrentIndex(0)
        elif index == TAB_FILE and self.w.btn_gcode_edit.isChecked():
            self.w.btn_gcode_edit.setChecked(False)
            self.w.btn_gcode_edit_clicked(False)
        if btn == self.w.btn_probe:
            self.probe.show()
            self.w.divider_line.show()
        elif self.probe is not None:
            self.probe.hide()
            self.w.divider_line.hide()
        self.w.main_tab_widget.setCurrentIndex(index)

    # gcode frame
    def cmb_gcode_history_clicked(self):
        if self.w.cmb_gcode_history.currentIndex() == 0: return
        filename = self.w.cmb_gcode_history.currentText().encode('utf-8')
        if filename == self.last_loaded_program:
            self.add_status("Selected program is already loaded")
        else:
            ACTION.OPEN_PROGRAM(filename)

    # program frame
    def btn_start_clicked(self, obj):
        if self.w.main_tab_widget.currentIndex() != 0:
            return
        if not STATUS.is_auto_mode():
            self.add_status("Must be in AUTO mode to run a program")
            return
        if STATUS.is_auto_running():
            self.add_status("Program is already running")
            return
        self.run_time = 0
        self.w.lbl_runtime.setText("00:00:00")
        if self.start_line <= 1:
            ACTION.RUN(self.start_line)
        else:
            # instantiate run from line preset dialog
            info = '<b>Running From Line: {} <\b>'.format(self.start_line)
            mess = {'NAME':'RUNFROMLINE', 'TITLE':'Preset Dialog', 'ID':'_RUNFROMLINE', 'MESSAGE':info, 'LINE':self.start_line}
            ACTION.CALL_DIALOG(mess)
        self.add_status("Started program from line {}".format(self.start_line))
        self.timer_on = True

    def btn_stop_clicked(self):
        if not self.w.btn_pause_spindle.isChecked(): return
        self.w.btn_pause_spindle.setChecked(False)
        self.btn_pause_spindle_clicked(False)

    def btn_reload_file_clicked(self):
        if self.last_loaded_program:
            self.w.progressBar.reset()
            self.add_status("Loaded program file {}".format(self.last_loaded_program))
            ACTION.OPEN_PROGRAM(self.last_loaded_program)

    def btn_pause_spindle_clicked(self, state):
        self.w.action_pause.setEnabled(not state)
        self.w.action_step.setEnabled(not state)
        if state:
        # set external offsets to lift spindle
            self.h['eoffset_enable'] = self.w.chk_eoffsets.isChecked()
            fval = float(self.w.lineEdit_eoffset_count.text())
            self.h['eoffset_count'] = int(fval)
            self.h['spindle_inhibit'] = True
        else:
            self.h['eoffset_count'] = 0
            self.h['eoffset_clear'] = True
            self.h['spindle_inhibit'] = False
            if STATUS.is_auto_running():
            # instantiate warning box
                info = "Wait for spindle at speed signal before resuming"
                mess = {'NAME':'MESSAGE', 'ICON':'WARNING', 'ID':'_wait_resume_', 'MESSAGE':'CAUTION', 'MORE':info, 'TYPE':'OK'}
                ACTION.CALL_DIALOG(mess)
        
    # offsets frame
    def btn_goto_location_clicked(self):
        dest = self.w.sender().property('location')
        if dest == 'home':
            x = float(self.w.lbl_home_x.text())
            y = float(self.w.lbl_home_y.text())
        elif dest == 'sensor':
            x = float(self.w.lineEdit_sensor_x.text())
            y = float(self.w.lineEdit_sensor_y.text())
        else:
            return
        if not STATUS.is_metric_mode():
            x = x / 25.4
            y = y / 25.4
        ACTION.CALL_MDI("G90")
        ACTION.CALL_MDI_WAIT("G53 G0 Z0")
        command = "G53 G0 X{:3.4f} Y{:3.4f}".format(x, y)
        ACTION.CALL_MDI_WAIT(command, 10)
 
    def btn_ref_laser_clicked(self):
        x = float(self.w.lineEdit_laser_x.text())
        y = float(self.w.lineEdit_laser_y.text())
        if not STATUS.is_metric_mode():
            x = x / 25.4
            y = y / 25.4
        self.add_status("Laser offsets set")
        command = "G10 L20 P0 X{:3.4f} Y{:3.4f}".format(x, y)
        ACTION.CALL_MDI(command)
    
    def btn_ref_camera_clicked(self):
        x = float(self.w.lineEdit_camera_x.text())
        y = float(self.w.lineEdit_camera_y.text())
        if not STATUS.is_metric_mode():
            x = x / 25.4
            y = y / 25.4
        self.add_status("Camera offsets set")
        command = "G10 L20 P0 X{:3.4f} Y{:3.4f}".format(x, y)
        ACTION.CALL_MDI(command)

    def btn_touchoff_clicked(self):
        if STATUS.get_current_tool() == 0:
            self.add_status("Cannot touchoff with no tool loaded")
            return
        if not STATUS.is_all_homed():
            self.add_status("Must be homed to perform tool touchoff")
            return
        # instantiate dialog box
        sensor = self.w.sender().property('sensor')
        info = "Ensure tooltip is within {} mm of tool sensor and click OK".format(self.w.lineEdit_max_probe.text())
        mess = {'NAME':'MESSAGE', 'ID':sensor, 'MESSAGE':'TOOL TOUCHOFF', 'MORE':info, 'TYPE':'OKCANCEL'}
        ACTION.CALL_DIALOG(mess)
        
    def chk_lock_wph_changed(self, state):
        self.w.lineEdit_work_height.setReadOnly(not state)

    # DRO frame
    def btn_home_all_clicked(self, obj):
        if self.home_all is False:
            ACTION.SET_MACHINE_HOMING(-1)
        else:
        # instantiate dialog box
            info = "Unhome All Axes?"
            mess = {'NAME':'MESSAGE', 'ID':'_unhome_', 'MESSAGE':'UNHOME ALL', 'MORE':info, 'TYPE':'OKCANCEL'}
            ACTION.CALL_DIALOG(mess)

    def btn_home_clicked(self):
        joint = self.w.sender().property('joint')
        axis = INFO.GET_NAME_FROM_JOINT.get(joint).lower()
        if self.w["dro_axis_{}".format(axis)].property('isHomed') is True:
            ACTION.SET_MACHINE_UNHOMED(joint)
        else:
            ACTION.SET_MACHINE_HOMING(joint)

    # override frame
    def slow_button_clicked(self, state):
        slider = self.w.sender().property('slider')
        current = self.w[slider].value()
        max = self.w[slider].maximum()
        if state:
            self.w.sender().setText("SLOW")
            self.w[slider].setMaximum(max / self.slow_jog_factor)
            self.w[slider].setValue(current / self.slow_jog_factor)
            self.w[slider].setPageStep(10)
        else:
            self.w.sender().setText("FAST")
            self.w[slider].setMaximum(max * self.slow_jog_factor)
            self.w[slider].setValue(current * self.slow_jog_factor)
            self.w[slider].setPageStep(100)

    def slider_maxv_changed(self, value):
        maxpc = (float(value) / self.max_linear_velocity) * 100
        self.w.lbl_maxv_percent.setText("{:3.0f} %".format(maxpc))

    def slider_rapid_changed(self, value):
        rapid = (float(value) / 100) * self.max_linear_velocity * self.factor
        self.w.lbl_max_rapid.setText("{:4.0f}".format(rapid))

    def btn_maxv_100_clicked(self):
        self.w.slider_maxv_ovr.setValue(self.max_linear_velocity)

    def btn_maxv_50_clicked(self):
        self.w.slider_maxv_ovr.setValue(self.max_linear_velocity / 2)

    # file tab
    def btn_gcode_edit_clicked(self, state):
        if not STATUS.is_on_and_idle():
            return
        if state:
            self.w.filemanager.hide()
            self.w.gcode_editor.show()
            self.w.gcode_editor.editMode()
        else:
            self.w.filemanager.show()
            self.w.gcode_editor.hide()
            self.w.gcode_editor.readOnlyMode()

    def btn_load_file_clicked(self):
        if self.w.btn_gcode_edit.isChecked(): return
        fname = self.w.filemanager.getCurrentSelected()
        if fname[1] is True:
            self.load_code(fname[0])

    def btn_copy_file_clicked(self):
        if self.w.btn_gcode_edit.isChecked(): return
        if self.w.sender() == self.w.btn_copy_right:
            source = self.w.filemanager_usb.getCurrentSelected()
            target = self.w.filemanager.getCurrentSelected()
        elif self.w.sender() == self.w.btn_copy_left:
            source = self.w.filemanager.getCurrentSelected()
            target = self.w.filemanager_usb.getCurrentSelected()
        else:
            return
        if source[1] is False:
            self.add_status("Specified source is not a file")
            return
        if target[1] is True:
            destination = os.path.join(os.path.dirname(target[0]), os.path.basename(source[0]))
        else:
            destination = os.path.join(target[0], os.path.basename(source[0]))
        try:
            copyfile(source[0], destination)
            self.add_status("Copied file from {} to {}".format(source[0], destination))
        except Exception as e:
            self.add_status("Unable to copy file. %s" %e)

    # tool tab
    def btn_m61_clicked(self):
        checked = self.w.tooloffsetview.get_checked_list()
        if len(checked) > 1:
            self.add_status("Select only 1 tool to load")
        elif checked:
            self.add_status("Loaded tool {}".format(checked[0]))
            ACTION.CALL_MDI("M61 Q{}".format(checked[0]))
        else:
            self.add_status("No tool selected")

    # status tab
    def btn_clear_status_clicked(self):
        STATUS.emit('update-machine-log', None, 'DELETE')

    def btn_save_status_clicked(self):
        text = self.w.machinelog.toPlainText()
        filename = self.w.lbl_clock.text().encode('utf-8')
        filename = 'status_' + filename.replace(' ','_') + '.txt'
        self.add_status("Saving Status file to {}".format(filename))
        with open(filename, 'w') as f:
            f.write(text)

    def btn_dimensions_clicked(self, state):
        self.w.gcodegraphics.show_extents_option = state
        self.w.gcodegraphics.clear_live_plotter()
        
    # camview tab
    def cam_zoom_changed(self, value):
        self.w.camview.scale = float(value) / 10

    def cam_dia_changed(self, value):
        self.w.camview.diameter = value

    def cam_rot_changed(self, value):
        self.w.camview.rotation = float(value) / 10

    # settings tab

    def chk_override_limits_checked(self, state):
        # only toggle override if it's not in synch with the button
        if state and not STATUS.is_limits_override_set():
            self.add_status("Override limits set")
            ACTION.TOGGLE_LIMITS_OVERRIDE()
        elif not state and STATUS.is_limits_override_set():
            error = ACTION.TOGGLE_LIMITS_OVERRIDE()
            # if override can't be released set the check button to reflect this
            if error == False:
                self.w.chk_override_limits.blockSignals(True)
                self.w.chk_override_limits.setChecked(True)
                self.w.chk_override_limits.blockSignals(False)
            else:
                self.add_status("Override limits not set")

    def chk_run_from_line_changed(self, state):
        if not state:
            self.w.btn_cycle_start.setText('CYCLE START')

    def chk_alpha_mode_changed(self, state):
        self.w.gcodegraphics.set_alpha_mode(state)

    def chk_inhibit_selection_changed(self, state):
        self.w.gcodegraphics.set_inhibit_selection(state)

    def chk_use_camera_changed(self, state):
        self.w.btn_ref_camera.setEnabled(state)
        if state :
            self.w.btn_camera.show()
        else:
            self.w.btn_camera.hide()

    def chk_use_sensor_changed(self, state):
        self.w.btn_tool_sensor.setEnabled(state)

    def chk_use_touchplate_changed(self, state):
        self.w.btn_touchplate.setEnabled(state)

    def chk_use_virtual_changed(self, state):
        codestring = "CALCULATOR" if state else "ENTRY"
        for i in ("x", "y", "z", "a"):
            self.w["axistoolbutton_" + i].set_dialog_code(codestring)
        if self.probe:
            self.probe.dialog_code = codestring
        if not state:
            self.w.stackedWidget_dro.setCurrentIndex(0)

    #####################
    # GENERAL FUNCTIONS #
    #####################
    def load_code(self, fname):
        if fname is None: return
        filename, file_extension = os.path.splitext(fname)
        if not file_extension in (".html", '.pdf'):
            if not (INFO.program_extension_valid(fname)):
                self.add_status("Unknown or invalid filename extension {}".format(file_extension))
                return
            self.w.cmb_gcode_history.addItem(fname)
            self.w.cmb_gcode_history.setCurrentIndex(self.w.cmb_gcode_history.count() - 1)
            self.w.cmb_gcode_history.setToolTip(fname)
            ACTION.OPEN_PROGRAM(fname)
            self.add_status("Loaded program file : {}".format(fname))
            self.w.main_tab_widget.setCurrentIndex(TAB_MAIN)
            self.w.filemanager.recordBookKeeping()

            # adjust ending to check for related HTML setup files
            fname = filename+'.html'
            if os.path.exists(fname):
                self.w.web_view.load(QtCore.QUrl.fromLocalFile(fname))
                self.add_status("Loaded HTML file : {}".format(fname))
            else:
                self.w.web_view.setHtml(self.html)

            # look for PDF setup files
            # load it with system program
            fname = filename+'.pdf'
            if os.path.exists(fname):
                url = QtCore.QUrl.fromLocalFile(fname)
                QtGui.QDesktopServices.openUrl(url)
                self.add_status("Loaded PDF file : {}".format(fname))
            return

        if file_extension == ".html":
            try:
                self.w.web_view.load(QtCore.QUrl.fromLocalFile(fname))
                self.add_status("Loaded HTML file : {}".format(fname))
                self.w.main_tab_widget.setCurrentIndex(TAB_SETUP)
                self.w.stackedWidget.setCurrentIndex(0)
                self.w.btn_setup.setChecked(True)
                self.w.jogging_frame.hide()
            except Exception as e:
                print("Error loading HTML file : {}".format(e))
        else:
            # load PDF with system program
            if os.path.exists(fname):
                url = QtCore.QUrl.fromLocalFile(fname)
                QtGui.QDesktopServices.openUrl(url)
                self.add_status("Loaded PDF file : {}".format(fname))

    def disable_spindle_pause(self):
        self.h['eoffset_count'] = 0
        self.h['spindle_inhibit'] = False
        if self.w.btn_pause_spindle.isChecked():
            self.w.btn_pause_spindle.setChecked(False)

    def touchoff(self, selector):
        if selector == 'touchplate':
            z_offset = float(self.w.lineEdit_touch_height.text())
        elif selector == 'sensor':
            z_offset = float(self.w.lineEdit_sensor_height.text()) - float(self.w.lineEdit_work_height.text())
        else:
            self.add_alarm("Unknown touchoff routine specified")
            return
        self.add_status("Touchoff to {} started".format(selector))
        max_probe = self.w.lineEdit_max_probe.text()
        search_vel = self.w.lineEdit_search_vel.text()
        probe_vel = self.w.lineEdit_probe_vel.text()
        ACTION.CALL_MDI("G21 G49")
        ACTION.CALL_MDI("G10 L20 P0 Z0")
        ACTION.CALL_MDI("G91")
        command = "G38.2 Z-{} F{}".format(max_probe, search_vel)
        if ACTION.CALL_MDI_WAIT(command, 10) == -1:
            ACTION.CALL_MDI("G90")
            return
        if ACTION.CALL_MDI_WAIT("G1 Z4.0"):
            ACTION.CALL_MDI("G90")
            return
        ACTION.CALL_MDI("G4 P0.5")
        command = "G38.2 Z-4.4 F{}".format(probe_vel)
        if ACTION.CALL_MDI_WAIT(command, 10) == -1:
            ACTION.CALL_MDI("G90")
            return
        command = "G10 L20 P0 Z{}".format(z_offset)
        ACTION.CALL_MDI_WAIT(command)
        command = "G1 Z10 F{}".format(search_vel)
        ACTION.CALL_MDI_WAIT(command)
        ACTION.CALL_MDI("G90")

    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            self.add_status('Machine must be ON and in Manual mode to jog')
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte()/60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    def add_status(self, message):
        self.w.statusbar.showMessage(message)
        STATUS.emit('update-machine-log', message, 'TIME')

    def enable_auto(self, state):
        if state is True:
            self.w.btn_main.setChecked(True)
            self.w.main_tab_widget.setCurrentIndex(TAB_MAIN)
            if self.probe is not None:
                self.probe.hide()
            self.w.stackedWidget_dro.setCurrentIndex(0)

    def enable_onoff(self, state):
        if state:
            self.add_status("Machine ON")
        else:
            self.add_status("Machine OFF")
        self.w.btn_pause_spindle.setChecked(False)
        self.h['eoffset_count'] = 0
        for widget in self.onoff_list:
            self.w[widget].setEnabled(state)

    def set_start_line(self, line):
        if self.w.chk_run_from_line.isChecked():
            self.start_line = line
            self.w.btn_cycle_start.setText("CYCLE START\nLINE {}".format(self.start_line))
        else:
            self.start_line = 1

    def use_keyboard(self):
        if self.w.chk_use_keyboard.isChecked():
            return True
        else:
            self.add_status('Keyboard shortcuts are disabled')
            return False

    def update_rpm(self, speed):
        rpm = int(speed)
        if rpm == 0:
            in_range = True
            at_speed = False
        else:
            in_range = (self.min_spindle_rpm <= int(speed) <= self.max_spindle_rpm)
            at_speed = self.h['spindle_at_speed']
        widget = self.w.lbl_spindle_set
        widget.setProperty('in_range', in_range)
        widget.style().unpolish(widget)
        widget.style().polish(widget)
        if at_speed is True:
            self.w.lbl_spindle_atspeed.setText('AT SPEED')
        else:
            self.w.lbl_spindle_atspeed.setText('')

    def update_runtimer(self):
        if self.timer_on is False or STATUS.is_auto_paused(): return
        self.time_tenths += 1
        if self.time_tenths == 10:
            self.time_tenths = 0
            self.run_time += 1
            hours, remainder = divmod(self.run_time, 3600)
            minutes, seconds = divmod(remainder, 60)
            self.w.lbl_runtime.setText("{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds))

    def stop_timer(self):
        if self.timer_on:
            self.timer_on = False
            self.add_status("Run timer stopped at {}".format(self.w.lbl_runtime.text()))

    def back(self):
        if os.path.exists(self.default_setup):
            self.w.web_view.load(QtCore.QUrl.fromLocalFile(self.default_setup))
        else:
            self.w.web_view.setHtml(self.html)
        #self.w.web_view.page().triggerAction(QWebEnginePage.Back)

    def forward(self):
        self.w.web_view.load(QtCore.QUrl.fromLocalFile(self.docs))
        #self.w.web_view.page().triggerAction(QWebEnginePage.Forward)

    def writer(self):
        WRITER.show()

    #####################
    # KEY BINDING CALLS #
    #####################

    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(True)

    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(False)

    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            ACTION.ABORT()

    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state and not STATUS.is_all_homed() and self.use_keyboard():
            ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_PAUSE(self,event,state,shift,cntrl):
        if state and STATUS.is_auto_mode() and self.use_keyboard():
            ACTION.PAUSE()

    def on_keycall_XPOS(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 2, -1, shift)
    
    def on_keycall_APOS(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self,event,state,shift,cntrl):
        if self.use_keyboard():
            self.kb_jog(state, 3, -1, shift, False)

    def on_keycall_F4(self,event,state,shift,cntrl):
        if state:
            mess = {'NAME':'CALCULATOR', 'TITLE':'Calculator', 'ID':'_calculator_'}
            ACTION.CALL_DIALOG(mess)

    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.styleeditor.load_dialog()

    ##############################
    # required class boiler code #
    ##############################
    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 29
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp, widgets, paths):
        self.hal = halcomp
        self.w = widgets
        self.stat = linuxcnc.stat()
        self.cmnd = linuxcnc.command()
        self.error = linuxcnc.error_channel()
        self.PATHS = paths
        self.IMAGE_PATH = paths.IMAGEDIR
        self.STYLEEDITOR = SSE(widgets, paths)
        global TOOLBAR
        TOOLBAR = ToolBarActions(path=paths)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')
        TOOLBAR.configure_action(self.w.actionEstop, 'estop')
        TOOLBAR.configure_action(self.w.actionMachineOn, 'power')
        TOOLBAR.configure_action(self.w.actionOpen, 'load')
        TOOLBAR.configure_action(self.w.actionReload, 'Reload')
        TOOLBAR.configure_action(self.w.actionRun, 'run')
        TOOLBAR.configure_action(self.w.actionPause, 'pause')
        TOOLBAR.configure_action(self.w.actionStop, 'abort')
        TOOLBAR.configure_action(self.w.actionSkip, 'block_delete')
        TOOLBAR.configure_action(self.w.actionOptionalStop, 'optional_stop')
        TOOLBAR.configure_action(self.w.actionZoomIn, 'zoom_in')
        TOOLBAR.configure_action(self.w.actionZoomOut, 'zoom_out')
        TOOLBAR.configure_action(self.w.actionFrontView, 'view_x')
        TOOLBAR.configure_action(self.w.actionSideView, 'view_y')
        TOOLBAR.configure_action(self.w.actionRotatedView, 'view_z2')
        TOOLBAR.configure_action(self.w.actionTopView, 'view_z')
        TOOLBAR.configure_action(self.w.actionPerspectiveView, 'view_p')
        TOOLBAR.configure_action(self.w.actionClearPlot, 'view_clear')
        TOOLBAR.configure_action(self.w.actionQuit, 'Quit',
                                 lambda d: self.w.close())
        TOOLBAR.configure_action(self.w.menuRecent, 'recent_submenu')
        TOOLBAR.configure_action(self.w.menuHoming, 'home_submenu')
        TOOLBAR.configure_action(self.w.actionProperties, 'gcode_properties')
        TOOLBAR.configure_action(self.w.actionCalibration, 'load_calibration')
        TOOLBAR.configure_action(self.w.actionStatus, 'load_status')
        TOOLBAR.configure_action(self.w.actionHalshow, 'load_halshow')
        TOOLBAR.configure_action(self.w.actionHalmeter, 'load_halmeter')
        TOOLBAR.configure_action(self.w.actionHalscope, 'load_halscope')
        TOOLBAR.configure_action(self.w.actionAbout, 'about')
        self.w.actionQuickRef.triggered.connect(self.quick_reference)

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F3, QtCore.Qt.Key_F5,
                        QtCore.Qt.Key_F5):
            if isinstance(receiver, OFFVIEW_WIDGET) or isinstance(
                    receiver, MDI_WIDGET):
                if is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                return True
            if isinstance(receiver, QtWidgets.QDialog):
                print 'dialog'
                return True
        try:
            KEYBIND.call(self, event, is_pressed, shift, cntrl)
            return True
        except Exception as e:
            #log.debug('Exception loading Macros:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            if e:
                print e
            #print 'from %s'% receiver
            return False

    ########################
    # callbacks from STATUS #
    ########################

    #######################
    # callbacks from form #
    #######################

    #####################
    # general functions #
    #####################
    def quick_reference(self):
        help1 = [
            ("F1", _("Emergency stop")),
            ("F2", _("Turn machine on")),
            ("", ""),
            ("X", _("Activate first axis")),
            ("Y", _("Activate second axis")),
            ("Z", _("Activate third axis")),
            ("A", _("Activate fourth axis")),
            ("` or 0,1..8",
             _("Activate first through ninth joint <br>if joints radiobuttons visible"
               )),
            ("", _("")),
            ("`,1..9,0", _("Set Feed Override from 0% to 100%")),
            ("", _("if axes radiobuttons visible")),
            (_(", and ."), _("Select jog speed")),
            (_("< and >"), _("Select angular jog speed")),
            (_("I, Shift-I"), _("Select jog increment")),
            ("C", _("Continuous jog")),
            (_("Home"), _("Send active joint home")),
            (_("Ctrl-Home"), _("Home all joints")),
            (_("Shift-Home"), _("Zero G54 offset for active axis")),
            (_("End"), _("Set G54 offset for active axis")),
            (_("Ctrl-End"), _("Set tool offset for loaded tool")),
            ("-, =", _("Jog active axis or joint")),
            (";, '", _("Select Max velocity")),
            ("", ""),
            (_("Left, Right"), _("Jog first axis or joint")),
            (_("Up, Down"), _("Jog second axis or joint")),
            (_("Pg Up, Pg Dn"), _("Jog third axis or joint")),
            (_("Shift+above jogs"), _("Jog at traverse speed")),
            ("[, ]", _("Jog fourth axis or joint")),
            ("", ""),
            ("D", _("Toggle between Drag and Rotate mode")),
            (_("Left Button"), _("Pan, rotate or select line")),
            (_("Shift+Left Button"), _("Rotate or pan")),
            (_("Right Button"), _("Zoom view")),
            (_("Wheel Button"), _("Rotate view")),
            (_("Rotate Wheel"), _("Zoom view")),
            (_("Control+Left Button"), _("Zoom view")),
        ]
        help2 = [
            ("F3", _("Manual control")),
            ("F5", _("Code entry (MDI)")),
            (_("Control-M"), _("Clear MDI history")),
            (_("Control-H"), _("Copy selected MDI history elements")),
            ("", _("to clipboard")),
            (_("Control-Shift-H"), _("Paste clipboard to MDI history")),
            ("L", _("Override Limits")),
            ("", ""),
            ("O", _("Open program")),
            (_("Control-R"), _("Reload program")),
            (_("Control-S"), _("Save g-code as")),
            ("R", _("Run program")),
            ("T", _("Step program")),
            ("P", _("Pause program")),
            ("S", _("Resume program")),
            ("ESC", _("Stop running program, or")),
            ("", _("stop loading program preview")),
            ("", ""),
            ("F7", _("Toggle mist")),
            ("F8", _("Toggle flood")),
            ("B", _("Spindle brake off")),
            (_("Shift-B"), _("Spindle brake on")),
            ("F9", _("Turn spindle clockwise")),
            ("F10", _("Turn spindle counterclockwise")),
            ("F11", _("Turn spindle more slowly")),
            ("F12", _("Turn spindle more quickly")),
            (_("Control-K"), _("Clear live plot")),
            ("V", _("Cycle among preset views")),
            ("F4", _("Cycle among preview, DRO, and user tabs")),
            ("@", _("toggle Actual/Commanded")),
            ("#", _("toggle Relative/Machine")),
            (_("Ctrl-Space"), _("Clear notifications")),
            (_("Alt-F, M, V"), _("Open a Menu")),
        ]
        help = zip(help1, help2)
        msg = QtWidgets.QDialog()
        msg.setWindowTitle("Quick Reference")
        button = QtWidgets.QPushButton("Ok")
        button.clicked.connect(lambda: msg.close())
        edit = QtWidgets.QTextEdit()
        edit.setLineWrapMode(0)

        mess = '''<TABLE border="1"><COLGROUP>
                <COL><COL align="char" char="."><THEAD>
                <TR><TH>Key <TH>Command<TH>Key <TH>Command
                <TBODY>'''
        for i, j in help:
            m = '<TR><TD><b>%s</b>        <TD>%s<TD><b>%s</b>        <TD>%s' % (
                i[0], i[1], j[0], j[1])
            mess += m
        mess += '</TABLE'
        edit.setText(mess)
        edit.setReadOnly(True)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(edit)
        layout.addWidget(button)
        msg.setLayout(layout)
        msg.setMinimumSize(700, 800)
        msg.show()
        retval = msg.exec_()

    # keyboard jogging from key binding calls
    # double the rate if fast is true
    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                self.cmnd.abort()

    # Linear Jogging
    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 30
0
 def __init__(self, halcomp, widgets, paths):
     self.hal = halcomp
     self.w = widgets
     self.PATHS = paths
     self.STYLEEDITOR = SSE(widgets, paths)
Esempio n. 31
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp,widgets,paths):
        self.hal = halcomp
        self.w = widgets
        self.PATHS = paths
        self.STYLEEDITOR = SSE(widgets,paths)
        self.picked_line = None
        STATUS.connect('general',self.return_value)
        STATUS.connect('graphics-line-selected', self.set_picked_line)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12','on_keycall_F12')

    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2,
                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F5,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = False
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self,event,is_pressed,shift,cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format (e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s'%(KEYBIND.convert(event),key)
            return False

    ########################
    # callbacks from STATUS #
    ########################
    # process the STATUS return message for run-from-line
    def return_value(self, obj, message):
        num = message['RETURN']
        code = bool(message['ID'] == '_RunFromLine_')
        name = bool(message['NAME'] == 'CALCULATOR')
        if num is not None and code and name:
            ACTION.RUN(int(num))

    def set_picked_line(self, obj, line):
        self.picked_line = line

    #######################
    # callbacks from form #
    #######################
    def full_screen(self, state):
        if state:
            self.w.stackedWidget_0.setCurrentIndex(1)
            self.w.widgetswitcher.show_id_widget(1)
        else:
            self.w.stackedWidget_0.setCurrentIndex(0)
            self.w.widgetswitcher.show_id_widget(0)

    def slow_jog_slider_changed(self, rate):
        if self.w.pbtn_jog_rate_slow.isChecked():
            ACTION.SET_JOG_RATE(rate)
    def fast_jog_slider_changed(self, rate):
        if self.w.pbtn_jog_rate_fast.isChecked():
            ACTION.SET_JOG_RATE(rate)

    def set_slow_rate(self, state):
        if state:
            ACTION.SET_JOG_RATE(self.w.scrb_jog_linear_slow.value())
    def set_fast_rate(self, state):
        if state:
            ACTION.SET_JOG_RATE(self.w.scrb_jog_linear_fast.value())

    def run_from_line_clicked(self):
        mess = {'NAME':'CALCULATOR','ID':'_RunFromLine_',
             'PRELOAD':self.picked_line,
               'TITLE':'Run From Line Dialog'}
        STATUS.emit('dialog-request', mess)

    #####################
    # general functions #
    #####################

    # keyboard jogging from key binding calls
    # double the rate if fast is true 
    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte()/60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())
    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())
    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)
    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                self.cmnd.abort()

    # Linear Jogging
    def on_keycall_XPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)
    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 32
0
class HandlerClass:

    ########################
    # **** INITIALIZE **** #
    ########################
    # widgets allows access to  widgets from the qtvcp files
    # at this point the widgets and hal pins are not instantiated
    def __init__(self, halcomp,widgets,paths):
        self.hal = halcomp
        self.w = widgets
        self.PATHS = paths
        self.STYLEEDITOR = SSE(widgets,paths)
        global TOOLBAR
        TOOLBAR = ToolBarActions(path=paths)
        STATUS.connect('general',self.return_value)
        STATUS.connect('motion-mode-changed',self.motion_mode)
        STATUS.connect('user-system-changed', self._set_user_system_text)

    ##########################################
    # Special Functions called from QTSCREEN
    ##########################################

    # at this point:
    # the widgets are instantiated.
    # the HAL pins are built but HAL is not set ready
    def initialized__(self):
        KEYBIND.add_call('Key_F12','on_keycall_F12')
        TOOLBAR.configure_submenu(self.w.menuRecent, 'recent_submenu')
        TOOLBAR.configure_submenu(self.w.menuHoming, 'home_submenu')
        TOOLBAR.configure_submenu(self.w.menuUnhome, 'unhome_submenu')
        TOOLBAR.configure_submenu(self.w.menuZeroCoordinateSystem, 'zero_systems_submenu')
        TOOLBAR.configure_action(self.w.actionEstop, 'estop')
        TOOLBAR.configure_action(self.w.actionMachineOn, 'power')
        TOOLBAR.configure_action(self.w.actionOpen, 'load')
        TOOLBAR.configure_action(self.w.actionReload, 'Reload')
        TOOLBAR.configure_action(self.w.actionRun, 'run')
        TOOLBAR.configure_action(self.w.actionPause, 'pause')
        TOOLBAR.configure_action(self.w.actionStop, 'abort')
        TOOLBAR.configure_action(self.w.actionSkip, 'block_delete')
        TOOLBAR.configure_action(self.w.actionOptionalStop, 'optional_stop')
        TOOLBAR.configure_action(self.w.actionZoomIn, 'zoom_in')
        TOOLBAR.configure_action(self.w.actionZoomOut, 'zoom_out')
        TOOLBAR.configure_action(self.w.actionFrontView, 'view_x')
        TOOLBAR.configure_action(self.w.actionSideView, 'view_y')
        TOOLBAR.configure_action(self.w.actionRotatedView, 'view_z2')
        TOOLBAR.configure_action(self.w.actionTopView, 'view_z')
        TOOLBAR.configure_action(self.w.actionPerspectiveView, 'view_p')
        TOOLBAR.configure_action(self.w.actionClearPlot, 'view_clear')
        TOOLBAR.configure_action(self.w.actionQuit, 'Quit', lambda d:self.w.close())
        TOOLBAR.configure_action(self.w.actionProperties, 'gcode_properties')
        TOOLBAR.configure_action(self.w.actionCalibration, 'load_calibration')
        TOOLBAR.configure_action(self.w.actionStatus, 'load_status')
        TOOLBAR.configure_action(self.w.actionHalshow, 'load_halshow')
        TOOLBAR.configure_action(self.w.actionHalmeter, 'load_halmeter')
        TOOLBAR.configure_action(self.w.actionHalscope, 'load_halscope')
        TOOLBAR.configure_action(self.w.actionAbout, 'about')
        TOOLBAR.configure_action(self.w.actionTouchoffWorkplace, 'touchoffworkplace')
        TOOLBAR.configure_action(self.w.actionEdit, 'edit', self.edit)
        TOOLBAR.configure_action(self.w.actionTouchoffFixture, 'touchofffixture')
        TOOLBAR.configure_action(self.w.actionRunFromLine, 'runfromline')
        self.w.actionQuickRef.triggered.connect(self.quick_reference)

    def processed_key_event__(self,receiver,event,is_pressed,key,code,shift,cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in(QtCore.Qt.Key_Escape,QtCore.Qt.Key_F1 ,QtCore.Qt.Key_F2,
                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F5,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = False
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self,event,is_pressed,shift,cntrl)
        except NameError as e:
            LOG.debug('Exception in KEYBINDING: {}'.format (e))
        except Exception as e:
            LOG.debug('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s'%(KEYBIND.convert(event),key)
            return False

    ########################
    # callbacks from STATUS #
    ########################

    # process the STATUS return message from set-tool-offset
    def return_value(self, w, message):
        num = message['RETURN']
        code = bool(message['ID'] == 'FORM__')
        name = bool(message['NAME'] == 'ENTRY')
        if num is not None and code and name:
            LOG.debug('message return:{}'.format (message))
            axis = message['AXIS']
            fixture = message['FIXTURE']
            ACTION.SET_TOOL_OFFSET(axis,num,fixture)
            STATUS.emit('update-machine-log', 'Set tool offset of Axis %s to %f' %(axis, num), 'TIME')

    def motion_mode(self, w, mode):
        #print STATUS.stat.joints
        #print STATUS.stat.kinematics_type
        #print INFO.AVAILABLE_AXES
        #print INFO.GET_NAME_FROM_JOINT
        if mode == linuxcnc.TRAJ_MODE_COORD:
            print 'Mode Coordinate'
        # Joint mode
        elif mode == linuxcnc.TRAJ_MODE_FREE:
            if STATUS.stat.kinematics_type == linuxcnc.KINEMATICS_IDENTITY:
                self.show_axes()
            else:
                print 'Mode Free'
                self.show_joints()
        elif mode == linuxcnc.TRAJ_MODE_TELEOP:
            print 'Mode Teleop'
            self.show_axes()

    #######################
    # callbacks from form #
    #######################

    def tool_offset_clicked(self):
        conversion = {0:"X", 1:"Y", 2:"Z", 3:"A", 4:"B", 5:"C", 6:"U", 7:"V", 8:"W"}
        axis = STATUS.get_selected_axis()
        mess = {'NAME':'ENTRY','ID':'FORM__', 'AXIS':conversion[axis],
            'FIXTURE':self.w.actionTouchoffWorkplace.isChecked(), 'TITLE':'Set Tool Offset'}
        STATUS.emit('dialog-request', mess)
        LOG.debug('message sent:{}'.format (mess))

    #####################
    # general functions #
    #####################

    def show_joints(self):
        for i in range(0,9):
            if i in INFO.AVAILABLE_JOINTS:
                self.w['ras_label_%s'%i].show()
                self.w['ras_%s'%i].show()
                self.w['ras_label_%s'%i].setText('J%d'%i)
                try:
                    self.w['machine_label_j%d'%i].setText('<html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Joint %d:</span></p></body></html>'%i)
                except:
                    pass
                continue
            self.w['ras_label_%s'%i].hide()
            self.w['ras_%s'%i].hide()

    def show_axes(self):
        for i in range(0,9):
            j = INFO.GET_NAME_FROM_JOINT.get(i)
            if j and len(j) == 1:
                self.w['ras_label_%s'%i].show()
                self.w['ras_%s'%i].show()
                self.w['ras_label_%s'%i].setText('%s'%j)
                try:
                    self.w['machine_label_j%d'%i].setText('<html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Machine %s:</span></p></body></html>' %j)
                except:
                    pass
                continue
            self.w['ras_label_%s'%i].hide()
            self.w['ras_%s'%i].hide()

    def _set_user_system_text(self, w, data):
        print data
        convert = { 1:"G54 ", 2:"G55 ", 3:"G56 ", 4:"G57 ", 5:"G58 ", 6:"G59 ", 7:"G59.1 ", 8:"G59.2 ", 9:"G59.3 "}
        unit = convert[int(data)]
        for i in ('x','y','z'):
            self.w['dro_label_g5x_%s'%i].imperial_template = unit + i.upper() + '%9.4f'
            self.w['dro_label_g5x_%s'%i].metric_template = unit + i.upper() + '%10.3f'
            self.w['dro_label_g5x_%s'%i].update_units()
        self.w.dro_label_g5x_r.angular_template = unit + 'R      %3.2f'
        self.w.dro_label_g5x_r.update_units()
        self.w.dro_label_g5x_r.update_rotation(None, STATUS.stat.rotation_xy)

    def edit(self, widget, state):
        if state:
            self.w.gcode_editor.editMode()
        else:
            self.w.gcode_editor.readOnlyMode()

    def quick_reference(self):
        help1 = [
    ("F1", _("Emergency stop")),
    ("F2", _("Turn machine on")),
    ("", ""),
    ("X", _("Activate first axis")),
    ("Y", _("Activate second axis")),
    ("Z", _("Activate third axis")),
    ("A", _("Activate fourth axis")),
    ("` or 0,1..8", _("Activate first through ninth joint <br>if joints radiobuttons visible")),
    ("", _("")),
    ("`,1..9,0", _("Set Feed Override from 0% to 100%")),
    ("", _("if axes radiobuttons visible")),
    (_(", and ."), _("Select jog speed")),
    (_("< and >"), _("Select angular jog speed")),
    (_("I, Shift-I"), _("Select jog increment")),
    ("C", _("Continuous jog")),
    (_("Home"), _("Send active joint home")),
    (_("Ctrl-Home"), _("Home all joints")),
    (_("Shift-Home"), _("Zero G54 offset for active axis")),
    (_("End"), _("Set G54 offset for active axis")),
    (_("Ctrl-End"), _("Set tool offset for loaded tool")),
    ("-, =", _("Jog active axis or joint")),
    (";, '", _("Select Max velocity")),

    ("", ""),
    (_("Left, Right"), _("Jog first axis or joint")),
    (_("Up, Down"), _("Jog second axis or joint")),
    (_("Pg Up, Pg Dn"), _("Jog third axis or joint")),
    (_("Shift+above jogs"), _("Jog at traverse speed")),
    ("[, ]", _("Jog fourth axis or joint")),

    ("", ""),
    ("D", _("Toggle between Drag and Rotate mode")),
    (_("Left Button"), _("Pan, rotate or select line")),
    (_("Shift+Left Button"), _("Rotate or pan")),
    (_("Right Button"), _("Zoom view")),
    (_("Wheel Button"), _("Rotate view")),
    (_("Rotate Wheel"), _("Zoom view")),
    (_("Control+Left Button"), _("Zoom view")),
]
        help2 = [
    ("F3", _("Manual control")),
    ("F5", _("Code entry (MDI)")),
    (_("Control-M"), _("Clear MDI history")),
    (_("Control-H"), _("Copy selected MDI history elements")),
    ("",          _("to clipboard")),
    (_("Control-Shift-H"), _("Paste clipboard to MDI history")),
    ("L", _("Override Limits")),
    ("", ""),
    ("O", _("Open program")),
    (_("Control-R"), _("Reload program")),
    (_("Control-S"), _("Save g-code as")),
    ("R", _("Run program")),
    ("T", _("Step program")),
    ("P", _("Pause program")),
    ("S", _("Resume program")),
    ("ESC", _("Stop running program, or")),
    ("", _("stop loading program preview")),
    ("", ""),
    ("F7", _("Toggle mist")),
    ("F8", _("Toggle flood")),
    ("B", _("Spindle brake off")),
    (_("Shift-B"), _("Spindle brake on")),
    ("F9", _("Turn spindle clockwise")),
    ("F10", _("Turn spindle counterclockwise")),
    ("F11", _("Turn spindle more slowly")),
    ("F12", _("Turn spindle more quickly")),
    (_("Control-K"), _("Clear live plot")),
    ("V", _("Cycle among preset views")),
    ("F4", _("Cycle among preview, DRO, and user tabs")),
    ("@", _("toggle Actual/Commanded")),
    ("#", _("toggle Relative/Machine")),
    (_("Ctrl-Space"), _("Clear notifications")),
    (_("Alt-F, M, V"), _("Open a Menu")),
]
        help =  zip(help1,help2)
        msg = QtWidgets.QDialog()
        msg.setWindowTitle("Quick Reference")
        button = QtWidgets.QPushButton("Ok")
        button.clicked.connect(lambda: msg.close())
        edit = QtWidgets.QTextEdit()
        edit.setLineWrapMode(0)

        mess = '''<TABLE border="1"><COLGROUP>
                <COL><COL align="char" char="."><THEAD>
                <TR><TH>Key <TH>Command<TH>Key <TH>Command
                <TBODY>'''
        for i,j in help:
            m='<TR><TD><b>%s</b>        <TD>%s<TD><b>%s</b>        <TD>%s'%(i[0],i[1],j[0],j[1])
            mess += m
        mess += '</TABLE'
        edit.setText(mess)
        edit.setReadOnly(True)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(edit)
        layout.addWidget(button)
        msg.setLayout(layout)
        msg.setMinimumSize(700,800)
        msg.show()
        retval = msg.exec_()


    # keyboard jogging from key binding calls
    # double the rate if fast is true 
    def kb_jog(self, state, joint, direction, fast = False, linear = True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte()/60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular()/60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    #####################
    # KEY BINDING CALLS #
    #####################

    # Machine control
    def on_keycall_ESTOP(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(STATUS.estop_is_clear())
    def on_keycall_POWER(self,event,state,shift,cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(not STATUS.machine_is_on())
    def on_keycall_HOME(self,event,state,shift,cntrl):
        if state:
            if STATUS.is_all_homed():
                ACTION.SET_MACHINE_UNHOMED(-1)
            else:
                ACTION.SET_MACHINE_HOMING(-1)
    def on_keycall_ABORT(self,event,state,shift,cntrl):
        if state:
            if STATUS.stat.interp_state == linuxcnc.INTERP_IDLE:
                self.w.close()
            else:
                self.cmnd.abort()

    # Linear Jogging
    def on_keycall_XPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self,event,state,shift,cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self,event,state,shift,cntrl):
        pass
        #self.kb_jog(state, 3, -1, shift, linear=False)

    def on_keycall_F12(self,event,state,shift,cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################

    ##############################
    # required class boiler code #
    ##############################

    def __getitem__(self, item):
        return getattr(self, item)
    def __setitem__(self, item, value):
        return setattr(self, item, value)
Esempio n. 33
0
class HandlerClass:
    def __init__(self, halcomp, widgets, paths):
        self.w = widgets
        self.PATHS = paths
        self.hal = halcomp
        INIPATH = os.environ.get('INI_FILE_NAME', '/dev/null')
        self.inifile = linuxcnc.ini(INIPATH)
        self.STYLEEDITOR = SSE(widgets, paths)
        KEYBIND.add_call('Key_F12', 'on_keycall_F12')

        STAT.connect('state-on', self.machine_on)
        STAT.connect('state-off', self.machine_off)
        STAT.connect('hard-limits-tripped', self.hard_limit_tripped)
        STAT.connect("interp-idle", self.interp_idle_changed)
        STAT.connect("user-system-changed", self.user_system_changed)
        STAT.connect("file-loaded", self.file_loaded)
        STAT.connect("all-homed", self.all_homed)
        STAT.connect("not-all-homed", self.not_homed)

        # some global variables
        self.axis_list = INFO.AVAILABLE_AXES
        self.joint_list = INFO.AVAILABLE_JOINTS
        self.max_velocity = INFO.MAX_LINEAR_VELOCITY
        self.system_list = [
            "G53", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2",
            "G59.3"
        ]
        self.home_location_x = self.inifile.find('JOINT_0', 'HOME')
        self.home_location_y = self.inifile.find('JOINT_1', 'HOME')
        self.home_location_z = self.inifile.find('JOINT_2', 'HOME')
        self.homed = False
        self.start_line = 0
        self.program_length = 0
        self.slow_jog_factor = 10
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.onoff_list = ["widget_controls", "Program_frame", "DRO_frame"]

    def initialized__(self):
        #self.init_pins()
        self.init_preferences()
        self.init_widgets()
        self.init_locations()

        # initialize DRO style
        for i in map(str.lower, self.axis_list):
            self.w["dro_axis_{}".format(i)].setStyle(
                self.w["dro_axis_{}".format(i)].style())

    #############################
    # SPECIAL FUNCTIONS SECTION #
    #############################
    #def init_pins(self):
    # these pins are needed so that the touchoff subroutine can read the variables
    #self.hal.newpin("touch_height", hal.HAL_FLOAT, hal.HAL_OUT)

    def init_preferences(self):
        if self.w.PREFS_:
            self.last_loaded_program = self.w.PREFS_.getpref(
                'last_file_path', None, str, 'BOOK_KEEPING')
            temp1 = self.w.PREFS_.getpref('Reload program', False, bool,
                                          'CUSTOM_FORM_ENTRIES')
        else:
            temp1 = False
            self.add_alarm("No preference file found")
        self.w.checkBox_reload_program.setChecked(temp1)

    def init_widgets(self):
        #laser power set
        MAX_POWER = int(self.inifile.find('LASER', 'POWER')) or 500
        FIX_VEL_1 = int(self.inifile.find('LASER', 'FIX_VEL_1')) or 100
        FIX_VEL_2 = int(self.inifile.find('LASER', 'FIX_VEL_2')) or 200
        FIX_VEL_3 = int(self.inifile.find('LASER', 'FIX_VEL_3')) or 400
        self.w.label_max_power.setText(str(MAX_POWER))
        self.w.slider_power.setMaximum(MAX_POWER)
        self.w.slider_power.setValue(MAX_POWER / 2)
        compare = lambda v, min, max: (v > min) and (v < max)
        if compare(FIX_VEL_1, 0, MAX_POWER) and compare(
                FIX_VEL_2, 0, MAX_POWER) and compare(FIX_VEL_3, 0, MAX_POWER):
            self.w.btn_power_1.setText(str(FIX_VEL_1))
            self.w.btn_power_2.setText(str(FIX_VEL_2))
            self.w.btn_power_3.setText(str(FIX_VEL_3))
        else:
            self.w.btn_power_1.setText(str(0))
            self.w.btn_power_2.setText(str(MAX_POWER / 2))
            self.w.btn_power_3.setText(str(MAX_POWER))
        #powder vel set
        MAX_POWER = int(self.inifile.find('POWDER', 'MAX_VEL')) or 29
        FIX_VEL_1 = float(self.inifile.find('POWDER', 'FIX_VEL_1')) or 1
        FIX_VEL_2 = float(self.inifile.find('POWDER', 'FIX_VEL_2')) or 5
        FIX_VEL_3 = float(self.inifile.find('POWDER', 'FIX_VEL_3')) or 10
        POWDER_NUM = int(self.inifile.find('POWDER', 'NUM')) or 1
        if POWDER_NUM > 26:
            POWDER_NUM = 26
        self.w.label_max_powder_vel.setText(str(MAX_POWER))
        self.w.slider_powder_vel.setMaximum(MAX_POWER * 10)
        self.w.slider_powder_vel.setValue(MAX_POWER / 2)
        if compare(FIX_VEL_1, 0, MAX_POWER) and compare(
                FIX_VEL_2, 0, MAX_POWER) and compare(FIX_VEL_3, 0, MAX_POWER):
            self.w.btn_powder_vel_1.setText(str(FIX_VEL_1))
            self.w.btn_powder_vel_2.setText(str(FIX_VEL_2))
            self.w.btn_powder_vel_3.setText(str(FIX_VEL_3))
        else:
            self.w.btn_powder_vel_1.setText(str(0))
            self.w.btn_powder_vel_2.setText(str(MAX_POWER / 2))
            self.w.btn_powder_vel_3.setText(str(MAX_POWER))
        for index in range(POWDER_NUM):
            self.w.comboBox_powder_num.addItem("PDR " + str(index + 1))
        #other set
        self.w.main_tab_widget.setCurrentIndex(0)
        self.w.slider_jog.setMaximum(self.max_velocity * 60)
        self.w.slider_jog.setValue(INFO.DEFAULT_LINEAR_JOG_VEL)
        self.w.slider_maxv.setMaximum(self.max_velocity * 60)
        self.w.slider_maxv.setValue(self.max_velocity * 60)
        self.w.slider_feed.setMaximum(INFO.MAX_FEED_OVERRIDE)
        self.w.slider_feed.setValue(100)
        self.w.slider_rapid.setMaximum(100)
        self.w.slider_rapid.setValue(100)
        self.w.checkBox_override_limits.setChecked(False)
        self.w.checkBox_override_limits.setEnabled(False)
        self.w.filemanager.show()
        self.w.gcode_editor.hide()
        self.w.btn_from_line.setEnabled(False)

    def init_locations(self):
        self.w.lbl_maxv.setText(str(self.max_velocity * 60))
        # home location
        if not self.home_location_x or not self.home_location_y or not self.home_location_z:
            self.w.btn_go_home.setEnabled(False)
            self.w.groupBox_home.hide()
            self.w.lbl_no_home.show()
            self.add_alarm("No valid home location found")
        else:
            self.w.lbl_home_x.setText(self.home_location_x)
            self.w.lbl_home_y.setText(self.home_location_y)
            self.w.lbl_no_home.hide()

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2):
            #                    QtCore.Qt.Key_F3,QtCore.Qt.Key_F4,QtCore.Qt.Key_F5):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, QtWidgets.QLineEdit):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                if isinstance(receiver2, TOOL_TABLE):
                    flag = True
                    break
                if isinstance(receiver2, OFFSET_VIEW):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STAT.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        # ok if we got here then try keybindings
        try:
            return KEYBIND.call(self, event, is_pressed, shift, cntrl)
        except NameError as e:
            self.add_alarm('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            LOG.error('Exception in KEYBINDING:', exc_info=e)
            print 'Error in, or no function for: %s in handler file for-%s' % (
                KEYBIND.convert(event), key)
            return False

    #########################
    # CALLBACKS FROM STATUS #
    #########################
    def machine_on(self, obj):
        for widget in self.onoff_list:
            self.w[widget].setEnabled(True)

    def machine_off(self, obj):
        for widget in self.onoff_list:
            self.w[widget].setEnabled(False)

    def gcode_line_selected(self, obj, data):
        if self.w.btn_from_line.isChecked():
            self.start_line = data
            self.w.btn_start.setText("START FROM {}".format(data))

    def interp_idle_changed(self, obj):
        self.start_line = 0
        self.w.btn_start.setText("START FROM 0")

    def user_system_changed(self, obj, data):
        sys = self.system_list[int(data)]
        self.w.actionbutton_rel.setText(sys)

    def file_loaded(self, obj, filename):
        if filename is not None:
            self.w.progressBar.setValue(0)
            self.last_loaded_program = filename
            fileobject = file(filename, 'r')
            lines = fileobject.readlines()
            fileobject.close()
            self.program_length = len(lines)
            self.start_line = 0
            self.w.btn_from_line.setEnabled(True)
            self.w.btn_start.setText("START FROM 0")
        else:
            self.w.btn_from_line.setEnabled(False)
            self.add_alarm("Filename not valid")

    def all_homed(self, obj):
        self.homed = True
        self.w.actionbutton_view_p.click()
        for i in map(str.lower, self.axis_list):
            self.w["dro_axis_{}".format(i)].setProperty('homed', True)
            self.w["dro_axis_{}".format(i)].setStyle(
                self.w["dro_axis_{}".format(i)].style())
        if self.last_loaded_program and self.w.checkBox_reload_program.checkState(
        ):
            ACTION.OPEN_PROGRAM(self.last_loaded_program)
            self.w.filemanager.updateDirectoryView(self.last_loaded_program)

    def not_homed(self, obj, data):
        self.homed = False
        for i in map(str.lower, self.axis_list):
            self.w["dro_axis_{}".format(i)].setProperty('homed', False)
            self.w["dro_axis_{}".format(i)].setStyle(
                self.w["dro_axis_{}".format(i)].style())

    def hard_limit_tripped(self, obj, tripped, list_of_tripped):
        self.w.checkBox_override_limits.setEnabled(tripped)
        if not tripped:
            self.w.checkBox_override_limits.setChecked(False)

    #######################
    # CALLBACKS FROM FORM #
    #######################
    def tool_widgets_enable(self, state):
        self.w.btn_laser_on.setEnabled(state)
        self.w.btn_gas_on.setEnabled(state)
        self.w.btn_laser_en.setEnabled(state)
        self.w.btn_light_on.setEnabled(state)
        self.w.btn_powder_on.setEnabled(state)
        self.w.comboBox_powder_num.setEnabled(state)

    # program frame
    def btn_start_clicked(self):
        if not STAT.is_auto_mode():
            return
        self.w.btn_from_line.setChecked(False)
        self.tool_widgets_enable(False)
        self.add_alarm("Started program from line {}".format(self.start_line))
        ACTION.RUN(self.start_line)

    def btn_abort_clicked(self):
        self.tool_widgets_enable(True)

    def btn_reload_file_clicked(self):
        if self.last_loaded_program:
            self.w.progressBar.setValue(0)
            ACTION.OPEN_PROGRAM(self.last_loaded_program)

    def btn_from_line_clicked(self, state):
        if state is False:
            self.start_line = 0
            self.w.btn_start.setText("START FROM 0")

    # tool slot
    def btn_laser_on_clicked(self, state):
        if not STAT.is_mdi_mode():
            return
        if state is False:
            ACTION.CALL_MDI_WAIT("M115")
        else:
            ACTION.CALL_MDI_WAIT("M105 P{}".format(
                self.w.slider_power.value()))

    def btn_laser_enable_clicked(self, state):
        if state is False:
            ACTION.CALL_MDI_WAIT("M114")
        else:
            ACTION.CALL_MDI_WAIT("M104")

    def btn_gas_on_clicked(self, state):
        if state is False:
            ACTION.CALL_MDI_WAIT("M116")
        else:
            ACTION.CALL_MDI_WAIT("M106")

    def btn_light_on_clicked(self, state):
        if state is False:
            ACTION.CALL_MDI_WAIT("M117")
        else:
            ACTION.CALL_MDI_WAIT("M107")

    def btn_powder_on_clicked(self, state):
        if state is False:
            ACTION.CALL_MDI_WAIT(
                "M118 P{}".format(self.w.comboBox_powder_num.currentIndex() +
                                  1))
        else:
            ACTION.CALL_MDI_WAIT("M108 P{} Q{}".format(
                self.w.comboBox_powder_num.currentIndex() + 1,
                float(self.w.slider_powder_vel.value()) / 10))

    # override frame
    def btn_slow_clicked(self, state):
        if state:
            current = self.w.slider_jog.value()
            self.w.btn_slow.setText("SLOW")
            self.w.slider_jog.setMaximum(self.max_velocity * 60 /
                                         self.slow_jog_factor)
            self.w.slider_jog.setValue(current / self.slow_jog_factor)
        else:
            current = self.w.slider_jog.value()
            self.w.btn_slow.setText("FAST")
            self.w.slider_jog.setMaximum(self.max_velocity * 60)
            self.w.slider_jog.setValue(current * self.slow_jog_factor)

    def btn_maxv_max_clicked(self):
        self.w.slider_maxv.setValue(self.max_velocity * 60)

    def btn_power_fix_1(self):
        self.w.slider_power.setValue(int(self.w.btn_power_1.text()))

    def btn_power_fix_2(self):
        self.w.slider_power.setValue(int(self.w.btn_power_2.text()))

    def btn_power_fix_3(self):
        self.w.slider_power.setValue(int(self.w.btn_power_3.text()))

    def btn_powder_vel_fix_1(self):
        self.w.slider_powder_vel.setValue(
            float(self.w.btn_powder_vel_1.text()) * 10)

    def btn_powder_vel_fix_2(self):
        self.w.slider_powder_vel.setValue(
            float(self.w.btn_powder_vel_2.text()) * 10)

    def btn_powder_vel_fix_3(self):
        self.w.slider_powder_vel.setValue(
            float(self.w.btn_powder_vel_3.text()) * 10)

    def sld_powder_vel_changed(self, vel):
        self.w.label_powder_vel.setText(str(float(vel) / 10))

    # file tab
    def btn_gcode_edit_clicked(self, state):
        if not STAT.is_on_and_idle():
            return
        for x in ["load", "next", "prev"]:
            self.w["btn_file_{}".format(x)].setEnabled(not state)
        if state:
            self.w.filemanager.hide()
            self.w.gcode_editor.show()
            self.w.gcode_editor.editMode()
        else:
            self.w.filemanager.show()
            self.w.gcode_editor.hide()
            self.w.gcode_editor.readOnlyMode()

    # alarm tab
    def btn_clear_alarms_clicked(self):
        STAT.emit('update-machine-log', None, 'DELETE')

    def btn_save_alarms_clicked(self):
        text = self.w.machinelog.toPlainText()
        filename = self.w.lbl_clock.text().encode('utf-8')
        filename = 'alarms_' + filename.replace(' ', '_') + '.txt'
        with open(filename, 'w') as f:
            f.write(text)

    def chk_override_limits(self, state):
        if state:
            print("Override limits set")
            ACTION.SET_LIMITS_OVERRIDE()
        else:
            print("Override limits not set")

    #####################
    # GENERAL FUNCTIONS #
    #####################

    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STAT.is_man_mode() or not STAT.machine_is_on():
            return
        if linear:
            distance = STAT.get_jog_increment()
            rate = STAT.get_jograte() / 60
        else:
            distance = STAT.get_jog_increment_angular()
            rate = STAT.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    def add_alarm(self, message):
        STAT.emit('update-machine-log', message, 'TIME')

    def alarm_added(self):
        self.w.led_alarm.setState(True)

    def tab_changed(self, index):
        self.w.btn_gcode_edit.setChecked(False)
        self.btn_gcode_edit_clicked(False)
        if index == 4:
            self.w.led_alarm.setState(False)

    #####################
    # KEY BINDING CALLS #
    #####################

    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(True)

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(False)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            ACTION.ABORT()

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state and self.homed is False:
            ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_XPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        self.kb_jog(state, 2, -1, shift)

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            self.STYLEEDITOR.load_dialog()

    ###########################
    # **** closing event **** #
    ###########################
# items to save in preference file

    def closing_cleanup__(self):
        if self.w.PREFS_:
            self.w.PREFS_.putpref('Reload program',
                                  self.w.checkBox_reload_program.checkState(),
                                  bool, 'CUSTOM_FORM_ENTRIES')

    ##############################
    # required class boiler code #
    ##############################
    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)