Import LinuxCNC source tree
This commit is contained in:
217
lib/python/qtvcp/widgets/operator_value_line.py
Normal file
217
lib/python/qtvcp/widgets/operator_value_line.py
Normal file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# QTVcp Widget - Operator-entered value line edit widget
|
||||
# optional dialog entry and optional MDI command issuing
|
||||
#
|
||||
# Copyright (c) 2025 Steve Richardson
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
###############################################################################
|
||||
|
||||
import os
|
||||
import linuxcnc
|
||||
import hal
|
||||
import time
|
||||
|
||||
import subprocess
|
||||
|
||||
from qtpy.QtWidgets import QLineEdit, QApplication
|
||||
from qtpy.QtCore import Qt, QEvent, Property
|
||||
|
||||
from qtvcp.core import Status, Action, Info
|
||||
from qtvcp.widgets.entry_widget import SoftInputWidget
|
||||
from qtvcp.lib.aux_program_loader import Aux_program_loader
|
||||
from qtvcp import logger
|
||||
|
||||
# Instiniate the libraries with global reference
|
||||
# STATUS gives us status messages from linuxcnc
|
||||
# AUX_PRGM holds helper program loader
|
||||
# INI holds ini details
|
||||
# ACTION gives commands to linuxcnc
|
||||
# LOG is for running code logging
|
||||
STATUS = Status()
|
||||
AUX_PRGM = Aux_program_loader()
|
||||
INFO = Info()
|
||||
ACTION = Action()
|
||||
LOG = logger.getLogger(__name__)
|
||||
|
||||
class OperatorValue(QLineEdit):
|
||||
def __init__(self, parent=None):
|
||||
super(OperatorValue, self).__init__(parent)
|
||||
|
||||
STATUS.connect('state-off', lambda w: self.setEnabled(False))
|
||||
STATUS.connect('state-estop', lambda w: self.setEnabled(False))
|
||||
STATUS.connect('interp-idle', lambda w: self.setEnabled(STATUS.machine_is_on()
|
||||
and (STATUS.is_all_homed()
|
||||
or INFO.NO_HOME_REQUIRED)))
|
||||
STATUS.connect('interp-run', lambda w: self.setEnabled(not STATUS.is_auto_mode()))
|
||||
STATUS.connect('all-homed', lambda w: self.setEnabled(STATUS.machine_is_on()))
|
||||
STATUS.connect('general',self.return_value)
|
||||
|
||||
class OperatorValueLine(OperatorValue):
|
||||
def __init__(self, parent=None):
|
||||
super(OperatorValueLine, self).__init__(parent)
|
||||
self._PARENT_WIDGET = parent
|
||||
self.dialog_code = 'CALCULATOR'
|
||||
self.soft_keyboard = False
|
||||
self.dialog_keyboard = False
|
||||
self.issue_mdi_on_submit = False
|
||||
self.issue_mdi_on_return = False
|
||||
self.mdi_command_format = "M3 S{value}"
|
||||
self.pending_value = False
|
||||
self._input_panel_full = SoftInputWidget(self, 'default')
|
||||
self.installEventFilter(self)
|
||||
|
||||
self.returnPressed.connect(self.handleReturnKey)
|
||||
|
||||
def handleReturnKey(self):
|
||||
self.setFocus()
|
||||
self.setCursorPosition(len(self.text())+1)
|
||||
if self.issue_mdi_on_return:
|
||||
self.pending_value = False
|
||||
self._style_polish('isPendingValue', self.pending_value)
|
||||
self.submit(self.mdi_command_format)
|
||||
|
||||
def submit(self, mdi_format):
|
||||
value = str(self.text()).strip()
|
||||
if value == '': return
|
||||
namespace = {'value': value}
|
||||
|
||||
ACTION.CALL_MDI(mdi_format.format(**namespace) + "\n")
|
||||
|
||||
# try/except is so designer will load
|
||||
def eventFilter(self, widget, event):
|
||||
if self.focusWidget() == widget and event.type() == QEvent.MouseButtonPress:
|
||||
if self.soft_keyboard:
|
||||
self._input_panel_full.show_input_panel(widget)
|
||||
elif self.dialog_keyboard:
|
||||
self.request_keyboard()
|
||||
return False
|
||||
|
||||
def request_keyboard(self):
|
||||
mess = {'NAME':self.dialog_code,'ID':'%s__' % self.objectName(),
|
||||
'TITLE':'Operator Value',
|
||||
'GEONAME':'OperatorValue_Keyboard_Dialog_{}'.format(self.dialog_code),
|
||||
}
|
||||
STATUS.emit('dialog-request', mess)
|
||||
LOG.debug('message sent:{}'.format (mess))
|
||||
|
||||
# process the STATUS return message
|
||||
def return_value(self, w, message):
|
||||
value = message['RETURN']
|
||||
code = bool(message.get('ID') == '%s__'% self.objectName())
|
||||
name = bool(message.get('NAME') == self.dialog_code)
|
||||
if code and name and value is not None:
|
||||
self.setFocus()
|
||||
self.setText(f"{value:.0f}")
|
||||
self.setCursorPosition(len(self.text())+1)
|
||||
if self.issue_mdi_on_submit:
|
||||
self.pending_value = False
|
||||
self._style_polish('isPendingValue', self.pending_value)
|
||||
self.submit(self.mdi_command_format)
|
||||
else:
|
||||
self.pending_value = True
|
||||
self._style_polish('isPendingValue', self.pending_value)
|
||||
|
||||
LOG.debug('message return:{}'.format (message))
|
||||
|
||||
def issue_mdi(self):
|
||||
self.submit(self.mdi_command_format)
|
||||
self.pending_value = False
|
||||
self._style_polish('isPendingValue', self.pending_value)
|
||||
|
||||
#########################################################################
|
||||
# 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
|
||||
#########################################################################
|
||||
|
||||
# force style sheet to update
|
||||
def _style_polish(self, prop, state):
|
||||
self.setProperty(prop, state)
|
||||
self.style().unpolish(self)
|
||||
self.style().polish(self)
|
||||
|
||||
def set_issue_mdi_on_submit(self, data):
|
||||
self.issue_mdi_on_submit = data
|
||||
def get_issue_mdi_on_submit(self):
|
||||
return self.issue_mdi_on_submit
|
||||
def reset_issue_mdi_on_submit(self):
|
||||
self.issue_mdi_on_submit = False
|
||||
|
||||
issue_mdi_on_submit_option = Property(bool, get_issue_mdi_on_submit, set_issue_mdi_on_submit, reset_issue_mdi_on_submit)
|
||||
|
||||
def set_issue_mdi_on_return(self, data):
|
||||
self.issue_mdi_on_return = data
|
||||
def get_issue_mdi_on_return(self):
|
||||
return self.issue_mdi_on_return
|
||||
def reset_issue_mdi_on_return(self):
|
||||
self.issue_mdi_on_return = False
|
||||
|
||||
issue_mdi_on_return_option = Property(bool, get_issue_mdi_on_return, set_issue_mdi_on_return, reset_issue_mdi_on_return)
|
||||
|
||||
def set_mdi_command_format(self, data):
|
||||
self.mdi_command_format = data
|
||||
def get_mdi_command_format(self):
|
||||
return self.mdi_command_format
|
||||
def reset_mdi_command_format(self):
|
||||
self.mdi_command_format = False
|
||||
|
||||
mdi_command_format_option = Property(str, get_mdi_command_format, set_mdi_command_format, reset_mdi_command_format)
|
||||
|
||||
|
||||
def set_soft_keyboard(self, data):
|
||||
self.soft_keyboard = data
|
||||
def get_soft_keyboard(self):
|
||||
return self.soft_keyboard
|
||||
def reset_soft_keyboard(self):
|
||||
self.soft_keyboard = False
|
||||
|
||||
soft_keyboard_option = Property(bool, get_soft_keyboard, set_soft_keyboard, reset_soft_keyboard)
|
||||
|
||||
def set_dialog_keyboard(self, data):
|
||||
self.dialog_keyboard = data
|
||||
def get_dialog_keyboard(self):
|
||||
return self.dialog_keyboard
|
||||
def reset_dialog_keyboard(self):
|
||||
self.dialog_keyboard = False
|
||||
|
||||
dialog_keyboard_option = Property(bool, get_dialog_keyboard, set_dialog_keyboard, reset_dialog_keyboard)
|
||||
|
||||
def set_dialog_code(self, data):
|
||||
self.dialog_code = data
|
||||
def get_dialog_code(self):
|
||||
return self.dialog_code
|
||||
def reset_dialog_code(self):
|
||||
self.dialog_code = False
|
||||
|
||||
dialog_code_option = Property(str, get_dialog_code, set_dialog_code, reset_dialog_code)
|
||||
|
||||
def set_pending_value(self, data):
|
||||
self.pending_value = data
|
||||
def get_pending_value(self):
|
||||
return self.pending_value
|
||||
def reset_pending_value(self):
|
||||
self.pending_value = False
|
||||
|
||||
isPendingValue = Property(bool, get_pending_value, set_pending_value, reset_pending_value)
|
||||
|
||||
|
||||
# for testing without editor:
|
||||
def main():
|
||||
import sys
|
||||
from qtpy.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
widget = OperatorValueLine()
|
||||
widget.show()
|
||||
sys.exit(app.exec())
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user