Skip to content

Commit ceb434c

Browse files
authored
Merge pull request #3346 from tangentaudio/master
QtVcp: new calc features, new homing option on ActionButton, new OperatorValueLine widget, indicatorMixin bugfix.
2 parents b4b0934 + 1e88d05 commit ceb434c

7 files changed

Lines changed: 374 additions & 4 deletions

File tree

3.31 KB
Loading

docs/src/gui/qtvcp-widgets.adoc

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,53 @@ It is a comma separated list of keyword and data:
14211421
*`SAVE:yes`*::
14221422
Shows a save button.
14231423

1424+
[[sub:qtvcp:widgets:operatorvalueline]]
1425+
=== `OperatorValueLine` - Operator Value Line Entry Widget
1426+
1427+
The operator enters values into this widget, which will be applied to a template and then optionally issued to the MDI either immediately or applied at a later time. The widget supports the optional popup calculator or keyboard for touchscreen-friendly entry.
1428+
1429+
image::images/qtvcp_operator_value.png["QtVCP OperatorValueLine",scale="25%"]
1430+
1431+
1432+
==== Formatting MDI Command
1433+
The widget supports a formatting option which is passed to Python's string `format()` to produce the final output for the MDI command. The special token `{value}` can be inserted anywhere in this format string where the value should appear. The formatting property is called `mdi_command_format_option`, e.g.:
1434+
1435+
* `M3 S{value}` to start the spindle at the speed entered by the operator.
1436+
* `M6 T{value} G43 H{value}` to issue a tool change and tool length offset change from the tool number entered
1437+
1438+
==== Automatic vs Deferred MDI Issue
1439+
The widget may be configured to automatically issue the MDI command upon submit when `issue_mdi_on_submit_option` is set to `True`. If `False` issuing the command may be done at a later time via a signal or function call from another widget.
1440+
1441+
In cases where `issue_mdi_on_submit_option` is `False`, calling the `issue_mdi()` function will issue the command. Slots attached to widgets such as PushButtons can trigger the MDI command when pressed, e.g.:
1442+
1443+
----
1444+
def setSpindleSpeed(self, event):
1445+
self.w.lineSpindleSpeed.issue_mdi()
1446+
ACTION.SET_MANUAL_MODE()
1447+
1448+
def setToolNumber(self, event):
1449+
self.w.lineToolNumber.issue_mdi()
1450+
ACTION.SET_MANUAL_MODE()
1451+
----
1452+
1453+
==== Pending State Styling Example
1454+
1455+
The widget tracks whether a value entered is pending and has not yet been issued via the property `isPendingValue`. This may be used to style the widget via the stylesheet. This can be used to alert the operator that they entered a value but another action must be taken to apply it.
1456+
1457+
The following style sheet excerpt will highlight the entry widget with a cyan background when values are pending and have not been applied.
1458+
1459+
----
1460+
#lineSpindleSpeed[isPendingValue=true],
1461+
#lineToolNumber[isPendingValue=true] {
1462+
background: cyan;
1463+
}
1464+
1465+
#lineSpindleSpeed[isPendingValue=false],
1466+
#lineToolNumber[isPendingValue=false] {
1467+
background: none;
1468+
}
1469+
----
1470+
14241471
[[sub:qtvcp:widgets:mdiline]]
14251472
=== `MDILine` - MDI Commands Line Entry Widget
14261473

@@ -2658,6 +2705,13 @@ When using ``STATUS``'s `request-dialog` function, the default launch name is *`
26582705

26592706
It is based on PyQt's _QDialog_.
26602707

2708+
==== INI file options for CALCULATOR
2709+
2710+
In the `DISPLAY` section of the INI file the following options may be set:
2711+
2712+
* `CALCULATOR_CONST_VALUES` - a comma-delimited list of common values you might enter, that will appear on a dedicated row of buttons at the bottom of the calculator. e.g. setting to `0.100,-0.100` would provide two buttons for +0.100 and -0.100 which are commonly used when edge-finding on inch mills. Up to six (6) values may be entered, beyond that the list will be truncated. Values must be valid floating point or integer.
2713+
* `CALCULATOR_ON_SHOW` - optionally set to `CLEAR_ALL` to issue a "Clear All" each time the calculator is shown. This will clear any previously entered values from the last time the calculator was used and open with the display value set to `0`
2714+
26612715
[[sub:qtvcp:widgets:runfromlinedialog]]
26622716
=== `RunFromLine` - Run-From-Line Dialog Widget
26632717

lib/python/qtvcp/plugins/widgets_plugin.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from PyQt5.QtDesigner import QPyDesignerCustomWidgetPlugin
55
from qtvcp.widgets.dro_widget import DROLabel
66
from qtvcp.widgets.mdi_line import MDILine
7+
from qtvcp.widgets.operator_value_line import OperatorValueLine
78
from qtvcp.widgets.mdi_history import MDIHistory
89
from qtvcp.widgets.mdi_touchy import MDITouchy
910
from qtvcp.widgets.gcode_editor import GcodeEditor, GcodeDisplay
@@ -107,6 +108,50 @@ def includeFile(self):
107108
return "qtvcp.widgets.mdi_line"
108109

109110

111+
####################################
112+
# Operator Value edit line
113+
####################################
114+
class OperatorValueLinePlugin(QPyDesignerCustomWidgetPlugin):
115+
def __init__(self, parent=None):
116+
super(OperatorValueLinePlugin, self).__init__(parent)
117+
self.initialized = False
118+
119+
def initialize(self, formEditor):
120+
if self.initialized:
121+
return
122+
self.initialized = True
123+
124+
def isInitialized(self):
125+
return self.initialized
126+
127+
def createWidget(self, parent):
128+
return OperatorValueLine(parent)
129+
130+
def name(self):
131+
return "OperatorValueLine"
132+
133+
def group(self):
134+
return "Linuxcnc - Controller"
135+
136+
def icon(self):
137+
return QtGui.QIcon(QtGui.QPixmap(ICON.get_path('operatorvalueline')))
138+
139+
def toolTip(self):
140+
return "Operator value edit line Widget"
141+
142+
def whatsThis(self):
143+
return ""
144+
145+
def isContainer(self):
146+
return True
147+
148+
def domXml(self):
149+
return '<widget class="OperatorValueLine" name="operatorvalueline" />\n'
150+
151+
def includeFile(self):
152+
return "qtvcp.widgets.operator_value_line"
153+
154+
110155
####################################
111156
# MDI History widget
112157
####################################

lib/python/qtvcp/widgets/action_button.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def __init__(self, parent=None):
107107
self.exit = False
108108
self.template_label = False
109109
self.lathe_mirror_x = False
110-
110+
self.home_no_unhome = False
111111
self.toggle_float = False
112112
self._toggle_state = 0
113113
self.joint = -1
@@ -473,15 +473,19 @@ def action(self, state=None):
473473
if state:
474474
ACTION.SET_MACHINE_HOMING(self.joint)
475475
else:
476-
ACTION.SET_MACHINE_UNHOMED(self.joint)
476+
if not self.home_no_unhome:
477+
ACTION.SET_MACHINE_UNHOMED(self.joint)
477478
else:
478479
if self.joint == -1:
479480
if STATUS.is_all_homed():
480-
ACTION.SET_MACHINE_UNHOMED(-1)
481+
if not self.home_no_unhome:
482+
ACTION.SET_MACHINE_UNHOMED(-1)
481483
else:
482484
ACTION.SET_MACHINE_HOMING(-1)
483485
elif STATUS.is_joint_homed(self.joint):
484-
ACTION.SET_MACHINE_UNHOMED(self.joint)
486+
if not self.home_no_unhome:
487+
ACTION.SET_MACHINE_UNHOMED(self.joint)
488+
pass
485489
else:
486490
ACTION.SET_MACHINE_HOMING(self.joint)
487491
elif self.unhome:
@@ -1422,6 +1426,14 @@ def get_lathe_mirror_x(self):
14221426
def reset_lathe_mirror_x(self):
14231427
self.lathe_mirror_x = False
14241428

1429+
def set_home_no_unhome(self, data):
1430+
self.home_no_unhome = data
1431+
def get_home_no_unhome(self):
1432+
return self.home_no_unhome
1433+
def reset_home_no_unhome(self):
1434+
self.home_no_unhome = False
1435+
1436+
14251437
# NON BOOL VARIABLES------------------
14261438
def set_incr_imperial(self, data):
14271439
self.jog_incr_imperial = data
@@ -1567,6 +1579,9 @@ def reset_ini_mdi_key(self):
15671579
machine_log_dialog_action = QtCore.pyqtProperty(bool, get_machine_log_dialog, set_machine_log_dialog, reset_machine_log_dialog)
15681580
lathe_mirror_x_action = QtCore.pyqtProperty(bool, get_lathe_mirror_x, set_lathe_mirror_x, reset_lathe_mirror_x)
15691581

1582+
1583+
home_no_unhome_option = QtCore.pyqtProperty(bool, get_home_no_unhome, set_home_no_unhome, reset_home_no_unhome)
1584+
15701585
def set_template_label(self, data):
15711586
self.template_label = data
15721587
def get_template_label(self):
@@ -1575,6 +1590,7 @@ def reset_template_label(self):
15751590
self.template_label = False
15761591
template_label_option = QtCore.pyqtProperty(bool, get_template_label, set_template_label, reset_template_label)
15771592

1593+
15781594
# NON BOOL
15791595
joint_number = QtCore.pyqtProperty(int, get_joint, set_joint, reset_joint)
15801596
axis_letter = QtCore.pyqtProperty(str, get_axis, set_axis, reset_axis)

lib/python/qtvcp/widgets/calculator.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ def __init__(self, parent=None):
109109
mainLayout.addWidget(self.to_inch_btn, 6, 1)
110110
mainLayout.addWidget(self.tpi_btn, 6, 2)
111111

112+
self.constButtons = []
113+
constValues = INFO.get_error_safe_setting('DISPLAY', 'CALCULATOR_CONST_VALUES', None)
114+
if constValues is not None:
115+
constValues = ''.join(constValues.split())
116+
for value in constValues.split(',')[:6]:
117+
constButton = QPushButton(value)
118+
constButton.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
119+
constButton.clicked.connect(self.constClicked)
120+
mainLayout.addWidget(constButton, 7, len(self.constButtons))
121+
self.constButtons.append(constButton)
122+
112123
self.backButton = QPushButton('Back')
113124
self.backButton.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
114125
self.backButton.clicked.connect(self.backAction)
@@ -146,6 +157,13 @@ def __init__(self, parent=None):
146157
STATUS.connect('all-homed', lambda w: self.axisButton.setEnabled(True))
147158
STATUS.connect('not-all-homed', lambda w, data: self.axisButton.setEnabled(False))
148159

160+
self.behaviorOnShow = INFO.get_error_safe_setting('DISPLAY', 'CALCULATOR_ON_SHOW', None)
161+
162+
def showEvent(self, event):
163+
if self.behaviorOnShow is not None:
164+
if self.behaviorOnShow.upper() == 'CLEAR_ALL':
165+
self.clearAll()
166+
149167
def digitClicked(self):
150168
clickedButton = self.sender()
151169
digitValue = int(clickedButton.text())
@@ -327,6 +345,17 @@ def convertClicked(self):
327345
self.display.setText(str(result))
328346
self.waitingForOperand = True
329347

348+
def constClicked(self):
349+
clickedButton = self.sender()
350+
constValue = float(clickedButton.text())
351+
352+
if self.waitingForOperand:
353+
self.display.clear()
354+
self.waitingForOperand = False
355+
356+
self.display.setText(str(constValue))
357+
358+
330359
def clear(self):
331360
if self.waitingForOperand:
332361
return

lib/python/qtvcp/widgets/indicatorMixIn.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ def getFlashRate(self):
572572
@pyqtSlot(int)
573573
def setFlashRate(self, value):
574574
self._flashRate = value
575+
self._timer.setInterval(self._flashRate)
575576
self.update()
576577

577578
def set_indicator_size(self, data):

0 commit comments

Comments
 (0)