Skip to content

Commit 2b40bb8

Browse files
committed
qtplasmac: enhance cutcritical dialog with checkboxes for each untoggled button
This allows the user a chance to toggle the buttons they forgot prior to starting a cut.
1 parent 0c57cc3 commit 2b40bb8

File tree

3 files changed

+72
-25
lines changed

3 files changed

+72
-25
lines changed

docs/src/plasma/qtplasmac.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3382,7 +3382,7 @@ There are three <<plasma:ext-hal-pin,External HAL Pins>> that are available to t
33823382
the pin names are `qtplasmac.ext_out_0`, `qtplasmac.ext_out_1`, and `qtplasmac.ext_out_2`.
33833383
HAL connections to these HAL pins need to be specified in a postgui HAL file as the HAL pins are not available until the QtPlasmaC GUI has loaded.
33843384

3385-
For toggle-halpin buttons, it is possible for the user to mark the associated HAL pin as being required to be turned "ON" before starting a cut sequence by adding "cutcritical" after the HAL pin in the button code. If *TORCH ENABLE* is checked and *CYCLE START*, *MANUAL CUT*, or *SINGLE CUT* are initiated while the "cutcritical" button is not "ON" then the user will receive a dialog warning them as such and asking to CONTINUE or CANCEL.
3385+
For toggle-halpin buttons, it is possible for the user to mark the associated HAL pin as being required to be turned "ON" before starting a cut sequence by adding "cutcritical" after the HAL pin in the button code. If *TORCH ENABLE* is checked and *CYCLE START*, *MANUAL CUT*, or *SINGLE CUT* are initiated while the "cutcritical" button is not "ON" then the user will receive a dialog warning them as such and asking to CONTINUE or CANCEL. The dialog will list all untoggled buttons with a corresponding checkbox and allow the user to choose which of the buttons should be toggled automatically upon clicking CONTINUE.
33863386

33873387
[source,{ini}]
33883388
----

share/qtvcp/screens/qtplasmac/qtplasmac_handler.py

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = '009.068'
1+
VERSION = '009.069'
22
LCNCVER = '2.10'
33

44
'''
@@ -1988,7 +1988,7 @@ def run_clicked(self):
19881988
log = _translate('HandlerClass', 'Run from line - here to end loaded')
19891989
log1 = _translate('HandlerClass', 'Start line')
19901990
STATUS.emit('update-machine-log', f'{log} - {log1}: {(self.startLine + 1)}', 'TIME')
1991-
elif not self.cut_critical_check():
1991+
elif self.cut_critical_toggle_check():
19921992
self.jobRunning = True
19931993
ACTION.RUN(0)
19941994
log = _translate('HandlerClass', 'Cycle started')
@@ -3465,7 +3465,7 @@ def dialog_rfl_type(self):
34653465
rflT.setWindowTitle(_translate('HandlerClass', 'Run From Line'))
34663466
run = QRadioButton(_translate('HandlerClass', 'HERE TO END'))
34673467
cut = QRadioButton(_translate('HandlerClass', 'THIS CUTPATH'))
3468-
lbl = QLabel()
3468+
lbl = QLabel('')
34693469
buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
34703470
buttonBox = QDialogButtonBox(buttons)
34713471
buttonBox.accepted.connect(rflT.accept)
@@ -3495,6 +3495,53 @@ def dialog_rfl_type(self):
34953495
else:
34963496
return {'cancel': True, 'type': 'end'}
34973497

3498+
def show_cut_critical_dialog(self, rcButtonList):
3499+
checkStyle = 'QCheckBox::indicator { margin-left: 8px; margin-right: 8px; }\n \
3500+
QCheckBox { font-size: 11pt; }'
3501+
ccr = QDialog(self.w)
3502+
ccr.setWindowTitle(_translate('HandlerClass', 'Untoggled Cut Critical Buttons'))
3503+
icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxWarning)
3504+
iconLabel = QLabel()
3505+
iconLabel.setPixmap(icon.pixmap(32, 32))
3506+
msg0 = _translate('HandlerClass', 'The following buttons have not been toggled')
3507+
msg1 = _translate('HandlerClass', 'Select items to be toggled when CONTINUE is clicked')
3508+
lbl0 = QLabel(f'\n{msg0}:\n')
3509+
lbl1 = QLabel('')
3510+
lbl2 = QLabel(f'\n{msg1}\n')
3511+
lbl2.setStyleSheet("padding-left: 1px;")
3512+
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
3513+
buttonBox.accepted.connect(ccr.accept)
3514+
buttonBox.rejected.connect(ccr.reject)
3515+
buttonBox.button(QDialogButtonBox.Ok).setText(_translate('HandlerClass', 'CONTINUE'))
3516+
buttonBox.button(QDialogButtonBox.Ok).setIcon(QIcon())
3517+
buttonBox.button(QDialogButtonBox.Ok).setMinimumWidth(120)
3518+
buttonBox.button(QDialogButtonBox.Cancel).setText(_translate('HandlerClass', 'CANCEL'))
3519+
buttonBox.button(QDialogButtonBox.Cancel).setIcon(QIcon())
3520+
hLayout = QHBoxLayout()
3521+
hLayout.addWidget(iconLabel)
3522+
hLayout.addWidget(lbl0)
3523+
hLayout.addStretch()
3524+
vLayout = QVBoxLayout()
3525+
vLayout.addLayout(hLayout)
3526+
checkBoxes = []
3527+
for bText in rcButtonList:
3528+
checkBox = QCheckBox(bText)
3529+
checkBox.setStyleSheet(checkStyle)
3530+
vLayout.addWidget(checkBox)
3531+
checkBoxes.append(checkBox)
3532+
if len(rcButtonList) > 1:
3533+
toggleAll = QCheckBox(_translate('HandlerClass', 'TOGGLE ALL'))
3534+
toggleAll.setStyleSheet(checkStyle)
3535+
vLayout.addWidget(lbl1)
3536+
vLayout.addWidget(toggleAll)
3537+
toggleAll.stateChanged.connect(lambda state: [checkBox.setChecked(state == Qt.Checked) for checkBox in checkBoxes])
3538+
vLayout.addWidget(lbl2)
3539+
vLayout.addWidget(buttonBox)
3540+
ccr.setLayout(vLayout)
3541+
result = ccr.exec_()
3542+
checkList = [checkBox.text() for checkBox in checkBoxes if checkBox.isChecked()]
3543+
return result, checkList
3544+
34983545
def invert_pin_state(self, halpin):
34993546
if 'qtplasmac.ext_out_' in halpin:
35003547
pin = f'out{halpin.split("out_")[1]}Pin'
@@ -3532,25 +3579,21 @@ def set_button_color(self):
35323579
if not self.button_normal_check(button):
35333580
self.button_normal(button)
35343581

3535-
def cut_critical_check(self):
3536-
rcButtonList = []
3537-
# halTogglePins format is: button name, run critical flag, button text
3538-
for halpin in self.halTogglePins:
3539-
if self.halTogglePins[halpin][1] and not hal.get_value(halpin):
3540-
rcButtonList.append(self.halTogglePins[halpin][2].replace('\n', ' '))
3541-
if rcButtonList and self.w.torch_enable.isChecked():
3542-
head = _translate('HandlerClass', 'Run Critical Toggle')
3543-
btn1 = _translate('HandlerClass', 'CONTINUE')
3544-
btn2 = _translate('HandlerClass', 'CANCEL')
3545-
msg0 = _translate('HandlerClass', 'Button not toggled')
3546-
joined = '\n'.join(rcButtonList)
3547-
msg1 = f'\n{joined}'
3548-
if self.dialog_show_yesno(QMessageBox.Warning, f'{head}', f'\n{msg0}:\n{msg1}', f'{btn1}', f'{btn2}'):
3549-
return False
3550-
else:
3551-
return True
3552-
else:
3553-
return False
3582+
def cut_critical_toggle_check(self):
3583+
# self.halTogglePins format is: button name, run critical flag, button text
3584+
checkDict = {
3585+
self.halTogglePins[halpin][2].replace('\n', ' '): halpin
3586+
for halpin in self.halTogglePins
3587+
if self.halTogglePins[halpin][1] and not hal.get_value(halpin)
3588+
}
3589+
if checkDict and self.w.torch_enable.isChecked():
3590+
result, checked = self.show_cut_critical_dialog(list(checkDict.keys()))
3591+
if result:
3592+
for bText in checked:
3593+
halpin = checkDict[bText]
3594+
self.user_button_down(int(self.halTogglePins[halpin][0].replace('button_','')))
3595+
return result
3596+
return True
35543597

35553598
def preview_stack_changed(self):
35563599
if self.w.preview_stack.currentIndex() == self.PREVIEW:
@@ -4787,7 +4830,7 @@ def single_cut(self):
47874830
self.vkb_show(True)
47884831
result = sC.exec_()
47894832
self.vkb_hide()
4790-
if not result or self.cut_critical_check():
4833+
if not result or not self.cut_critical_toggle_check():
47914834
self.set_buttons_state([self.idleList, self.idleOnList, self.idleHomedList], True)
47924835
return
47934836
self.PREFS.putpref('X length', xLength.value(), float, 'SINGLE CUT')
@@ -4821,7 +4864,7 @@ def manual_cut(self):
48214864
self.button_normal(self.mcButton)
48224865
log = _translate('HandlerClass', 'Manual cut aborted')
48234866
STATUS.emit('update-machine-log', log, 'TIME')
4824-
elif STATUS.machine_is_on() and STATUS.is_all_homed() and STATUS.is_interp_idle() and not self.cut_critical_check():
4867+
elif STATUS.machine_is_on() and STATUS.is_all_homed() and STATUS.is_interp_idle() and self.cut_critical_toggle_check():
48254868
probeError, errMsg = self.bounds_check_probe(True)
48264869
if probeError:
48274870
head = _translate('HandlerClass', 'Axis Limit Error')

share/qtvcp/screens/qtplasmac/versions.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ <h2>QtPlasmaC Version History - LinuxCNC 2.10</h2>
2626
</table>
2727
<br>
2828
<!--- ****** ADD NEXT VERSION BELOW THIS LINE ****** --->
29+
<br><b><u>009.069 2025 July 28</u></b>
30+
<ul style="margin:0;">
31+
<li>enhance cutcritical dialog with checkboxes for each untoggled button</li>
32+
2933
<br><b><u>009.068 2025 July 25</u></b>
3034
<ul style="margin:0;">
3135
<li>"VEL:" label now indicates active velocity reduction and shows commanded feed rate percentage</li>

0 commit comments

Comments
 (0)