Files
linuxcncAllWasm/lib/python/qtvcp/widgets/jog_increments.py
2026-08-20 06:17:39 +08:00

221 lines
7.9 KiB
Python

#!/usr/bin/env python3
# qtvcp
#
# Copyright (c) 2017 Chris Morley <chrisinnanaimo@hotmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#################################################################################
from qtpy import QtCore, QtWidgets
import hal
from qtvcp.widgets.widget_baseclass import _HalWidgetBase
from qtvcp.core import Status, Info
from qtvcp import logger
# Instantiate the libraries with global reference
# STATUS gives us status messages from linuxcnc
# INFO is INI file details
# LOG is for running code logging
STATUS = Status()
INFO = Info()
LOG = logger.getLogger(__name__)
# Force the log level for this module
#LOG.setLevel(logger.DEBUG) # One of DEBUG, INFO, WARNING, ERROR, CRITICAL
class JogIncrements(QtWidgets.QComboBox, _HalWidgetBase):
def __init__(self, parent=None):
super(JogIncrements, self).__init__(parent)
self._pin_name = ''
self.linear = True
self._block_signal = False
# Default to continuous jogging (selection 0)
# with a combo box display, it's assumed the showing increment
# is valid - so we must update the rate if the units mode changes.
def _hal_init(self):
# TODO should this be optional?
if 1==1:
if self._pin_name == '':
pname = self.HAL_NAME_
else:
pname = self._pin_name
self.hal_pin = self.HAL_GCOMP_.newpin(pname, hal.HAL_FLOAT, hal.HAL_OUT)
if self.linear:
for item in (INFO.JOG_INCREMENTS):
self.addItem(item)
STATUS.connect('metric-mode-changed', self._switch_units)
STATUS.connect('jogincrement-changed', lambda w, value, text: self._checkincrements(value, text))
else:
for item in (INFO.ANGULAR_INCREMENTS):
self.addItem(item)
STATUS.connect('jogincrement-angular-changed', lambda w, value, text: self._checkincrements(value, text))
self.currentIndexChanged.connect(self.selectionchange)
self.selectionchange(0)
# if units switch - current jog rate in invalid
def _switch_units(self, w, data):
if self.currentIndex() > 0:
self.selectionchange(-1)
# search the combo box for the value STATUS sent us
# If there is a match, change the combobox to it
# otherwise display a blank in the combobox.
# in this way if some other widget sets a rate change
# the combo box doesn't lie
def _checkincrements(self,value, text):
self.hal_pin.set(value)
for count in range(self.count()):
label = self.itemText(count)
try:
number = float(label.rstrip(" inchmuildeg").lower())
except:
number = None
# assume continuous jogging (selection 0)
if number is None:
machn_incr = 0
else:
if self.linear:
machn_incr = self.parse_increment(label)
else:
machn_incr = self.parse_angular_increment(label)
#print count,self.itemText(count), machn_incr,value
if machn_incr is not None and round(machn_incr,6) == round(value,6):
self._block_signal = True
self.setCurrentIndex(count)
self._block_signal = False
return
self.setCurrentIndex(-1)
def selectionchange(self, i):
if self._block_signal: return
text = str(self.currentText())
if i == -1 and text == '': return
try:
# continuous jog (selection 0)
if i == 0:
inc = 0
else:
if self.linear:
inc = self.parse_increment(text)
else:
inc = self.parse_angular_increment(text)
except Exception as e:
LOG.debug('Exception parsing increment - setting increment to None', exc_info=e)
inc = None
if inc is None:
LOG.warning("parsed: text not recognized : {} Increment: {}".format(text, inc))
return
if self.linear:
LOG.debug("Linear Current index: {} Increment: {} , selection changed {}".format(i, inc, text))
STATUS.set_jog_increments(inc, text)
else:
LOG.debug("Angular Current index: {} Increment: {} , selection changed {}".format(i, inc, text))
STATUS.set_jog_increment_angular(inc, text)
def parse_angular_increment(self, jogincr):
scale = 1
if jogincr.endswith("deg"):
scale = 1
incr = jogincr.rstrip(" deg")
incr = float(incr)
return incr * scale
# We convert INI parced increments to machine units
def parse_increment(self, jogincr):
if jogincr.endswith("mm"):
scale = self.conversion(1)
elif jogincr.endswith("cm"):
scale = self.conversion(10)
elif jogincr.endswith("um"):
scale = self.conversion(.001)
elif jogincr.endswith("in") or jogincr.endswith("inch"):
scale = self.conversion(1., metric = False)
elif jogincr.endswith("mil"):
scale = self.conversion(.001, metric = False)
else:
scale = 1
incr = jogincr.rstrip(" inchmuil")
try:
if "/" in incr:
p, q = incr.split("/")
incr = float(p) / float(q)
else:
incr = float(incr)
except:
return None
LOG.debug("parsed: text: {} Increment: {} scaled: {}".format(jogincr, incr, (incr * scale)))
return incr * scale
# This does the conversion
# calling function must tell us if the data is metric or not.
def conversion(self, data, metric = True):
if STATUS.is_metric_mode():
if metric:
return INFO.convert_metric_to_machine(data)
else:
return INFO.convert_imperial_to_machine(data)
else:
if metric:
return INFO.convert_metric_to_machine(data)
else:
return INFO.convert_imperial_to_machine(data)
#########################################################################
# This is how designer can interact with our widget properties.
# designer will show the Property properties in the editor
# it will use the get set and reset calls to do those actions
#
# _toggle_properties makes it so we can only select one option
########################################################################
def _toggle_properties(self, picked):
data = ('linear')
for i in data:
if not i == picked:
self[i+'_option'] = False
# BOOL VARIABLES----------------------
def set_linear(self, data):
self.linear = data
def get_linear(self):
return self.linear
def reset_linear(self):
self.linear = True
# designer will show these properties in this order:
# BOOL
linear_option = QtCore.Property(bool, get_linear, set_linear, reset_linear)
# VARIABLES---------------------------
def set_pin_name(self, value):
self._pin_name = value
def get_pin_name(self):
return self._pin_name
def reset_pin_name(self):
self._pin_name = ''
pinName = QtCore.Property(str, get_pin_name, set_pin_name, reset_pin_name)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
combo = JogIncrements()
combo.show()
sys.exit(app.exec())