239 lines
8.3 KiB
Python
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()
|