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

239 lines
8.3 KiB
Python

#!/usr/bin/env python3
#
# QTVcp Widget
# Copyright (c) 2018 Chris Morley
#
# 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.QtWidgets import (QToolButton, QMenu, QAction,
QComboBox, QWidgetAction)
from qtpy.QtCore import Property
from qtpy.QtGui import QIcon
from qtvcp.widgets.widget_baseclass import _HalWidgetBase
from qtvcp.widgets.indicatorMixIn import IndicatedMixIn
from qtvcp.core import Status, Action, Info
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()
INFO = Info()
ACTION = Action()
LOG = logger.getLogger(__name__)
# Force the log level for this module
#LOG.setLevel(logger.DEBUG) # One of DEBUG, INFO, WARNING, ERROR, CRITICAL
class ActionToolButton(QToolButton, IndicatedMixIn):
def __init__(self, parent=None):
super(ActionToolButton, self).__init__(parent)
self._gridSize = 0
self._userView = True
self._optionMenu = False
def buildMenu(self):
if self._userView:
settingMenu = QMenu(self)
self.settingMenu = settingMenu
self.recordButton = QAction(QIcon('exit24.png'), 'Record View', settingMenu)
self.recordButton.triggered.connect(self.recordView)
settingMenu.addAction(self.recordButton)
self.setMenu(settingMenu)
self.clicked.connect(self.setView)
elif self._optionMenu:
settingMenu = QMenu(self)
self.settingMenu = settingMenu
self.showGridAct = QAction( 'Show Grid', settingMenu, checkable=True)
self.showGridAct.setChecked(True)
self.showGridAct.triggered.connect(self.showGrid)
settingMenu.addAction(self.showGridAct)
self.comboBox = QComboBox(self)
for i in (INFO.GRID_INCREMENTS):
self.comboBox.addItem(i)
self.comboBox.currentTextChanged.connect(self.setGridSize)
wid = QWidgetAction(self)
wid.setDefaultWidget(self.comboBox)
settingMenu.addAction(wid)
self.showDimsAct = QAction( 'Show Dimensions', settingMenu, checkable=True)
self.showDimsAct.setChecked(True)
self.showDimsAct.triggered.connect(self.showDims)
settingMenu.addAction(self.showDimsAct)
self.showDROAct = QAction( 'Show DRO', settingMenu, checkable=True)
self.showDROAct.setChecked(False)
self.showDROAct.triggered.connect(self.showDRO)
settingMenu.addAction(self.showDROAct)
self.showDTGAct = QAction( 'Show DTG', settingMenu, checkable=True)
self.showDTGAct.setChecked(False)
self.showDTGAct.triggered.connect(self.showDTG)
settingMenu.addAction(self.showDTGAct)
self.showLargeAct = QAction( 'Large Font', settingMenu, checkable=True)
self.showLargeAct.setChecked(False)
self.showLargeAct.triggered.connect(self.showLarge)
settingMenu.addAction(self.showLargeAct)
self.setMenu(settingMenu)
# Override setText function so we can toggle displayed text
def setText(self, text):
if not self._state_text:
super(ActionToolButton,self).setText(text)
return
if self.isCheckable():
if self.isChecked():
super(ActionToolButton,self).setText(self._true_string)
else:
super(ActionToolButton,self).setText(self._false_string)
elif self._indicator_state:
super(ActionToolButton,self).setText(self._true_string)
else:
super(ActionToolButton,self).setText(self._false_string)
def _hal_init(self):
def homed_on_test():
return (STATUS.machine_is_on()
and (STATUS.is_all_homed() or INFO.NO_HOME_REQUIRED))
super(ActionToolButton, self)._hal_init()
self.buildMenu()
def recordView(self):
ACTION.SET_GRAPHICS_VIEW('record-view')
def setView(self):
ACTION.SET_GRAPHICS_VIEW('set-recorded-view')
def showDims(self, data):
if data:
ACTION.SET_GRAPHICS_VIEW('dimensions-on')
else:
ACTION.SET_GRAPHICS_VIEW('dimensions-off')
def showGrid(self, data):
if data:
ACTION.SET_GRAPHICS_GRID_SIZE(self._gridSize)
else:
ACTION.SET_GRAPHICS_VIEW('grid-off')
def setGridSize(self, data):
size = self.parse_increment(data)
self._gridSize = size
if self.showGridAct.isChecked():
ACTION.SET_GRAPHICS_GRID_SIZE(size)
def showDRO(self, data):
if data:
ACTION.SET_GRAPHICS_VIEW('overlay-dro-on')
else:
ACTION.SET_GRAPHICS_VIEW('overlay-dro-off')
def showDTG(self, data):
if data:
ACTION.SET_GRAPHICS_VIEW('dtg-on')
else:
ACTION.SET_GRAPHICS_VIEW('dtg-off')
def showLarge(self, data):
if data:
ACTION.SET_GRAPHICS_VIEW('set-large-dro')
else:
ACTION.SET_GRAPHICS_VIEW('set-small-dro')
###################################################
# helper functions
###################################################
# We convert INI parced increments to machine units
def parse_increment(self, gridincr):
if gridincr.endswith("mm"):
scale = self.conversion(1)
elif gridincr.endswith("cm"):
scale = self.conversion(10)
elif gridincr.endswith("um"):
scale = self.conversion(.001)
elif gridincr.endswith("in") or gridincr.endswith("inch"):
scale = self.conversion(1., metric = False)
elif gridincr.endswith("mil"):
scale = self.conversion(.001, metric = False)
else:
scale = 1
incr = gridincr.rstrip(" inchmuil")
try:
if "/" in incr:
p, q = incr.split("/")
incr = float(p) / float(q)
else:
incr = float(incr)
except:
return None
LOG.verbose("parsed: text: {} Increment: {} scaled: {}".format(gridincr, 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
#
########################################################################
# user view
def setViewAction(self, state):
self._userView = state
def getViewAction(self):
return self._userView
userViewAction = Property(bool, getViewAction, setViewAction)
# option menu
def setOptionMenu(self, state):
self._optionMenu = state
def getOptionMenu(self):
return self._optionMenu
OptionMenuAction = Property(bool, getOptionMenu, setOptionMenu)
# for testing without editor:
def main():
import sys
from qtpy.QtWidgets import QApplication
app = QApplication(sys.argv)
widget = ActionToolButton()
widget.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()