Import LinuxCNC source tree
This commit is contained in:
663
lib/python/qtvcp/widgets/tool_offsetview.py
Normal file
663
lib/python/qtvcp/widgets/tool_offsetview.py
Normal file
@@ -0,0 +1,663 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Qtvcp widget
|
||||
# Copyright (c) 2017 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.
|
||||
###############################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import operator
|
||||
|
||||
from qtpy.QtCore import Qt, QAbstractTableModel, Property, QSize, Slot
|
||||
from qtpy.QtGui import QColor, QIcon
|
||||
from qtpy.QtWidgets import (QTableView, QAbstractItemView, QCheckBox,
|
||||
QItemEditorFactory,QDoubleSpinBox,QSpinBox,QStyledItemDelegate, QApplication, QHeaderView)
|
||||
|
||||
# QVariant type IDs for ItemEditorFactory: use QVariant constants on PyQt5,
|
||||
# fall back to the stable Qt metatype integers on PyQt6 where they were removed.
|
||||
try:
|
||||
from qtpy.QtCore import QVariant as _QVariant
|
||||
_DOUBLE_TYPE = _QVariant.Double
|
||||
_INT_TYPE = _QVariant.Int
|
||||
except AttributeError:
|
||||
_DOUBLE_TYPE = 6 # QMetaType::Double
|
||||
_INT_TYPE = 2 # QMetaType::Int
|
||||
from qtvcp.widgets.widget_baseclass import _HalWidgetBase
|
||||
from qtvcp.core import Status, Action, Info, Tool, Path
|
||||
from qtvcp import logger
|
||||
|
||||
#BASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ".."))
|
||||
#LOCALEDIR = os.path.join(BASE, "share", "locale")
|
||||
#locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
# Instiniate the libraries with global reference
|
||||
# STATUS gives us status messages from linuxcnc
|
||||
# INI holds ini details
|
||||
# ACTION gives commands to linuxcnc
|
||||
# LOG is for running code logging
|
||||
STATUS = Status()
|
||||
ACTION = Action()
|
||||
INFO = Info()
|
||||
TOOL = Tool()
|
||||
PATH = Path()
|
||||
LOG = logger.getLogger(__name__)
|
||||
|
||||
# Force the log level for this module
|
||||
#LOG.setLevel(logger.DEBUG) # One of DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||
|
||||
ICONPATH = os.path.join(PATH.SHAREDIR, 'images/widgets/tool_offsetview')
|
||||
|
||||
# custom spinbox controls for editing
|
||||
class ItemEditorFactory(QItemEditorFactory):
|
||||
def __init__(self):
|
||||
super(ItemEditorFactory,self).__init__()
|
||||
|
||||
def createEditor(self, userType, parent):
|
||||
if userType == _DOUBLE_TYPE:
|
||||
doubleSpinBox = QDoubleSpinBox(parent)
|
||||
doubleSpinBox.setDecimals(4)
|
||||
doubleSpinBox.setMaximum(99999)
|
||||
doubleSpinBox.setMinimum(-99999)
|
||||
return doubleSpinBox
|
||||
elif userType == _INT_TYPE:
|
||||
spinBox = QSpinBox(parent)
|
||||
spinBox.setMaximum(20000)
|
||||
spinBox.setMinimum(1)
|
||||
return spinBox
|
||||
else:
|
||||
return super(ItemEditorFactory,self).createEditor(userType, parent)
|
||||
|
||||
class ToolOffsetView(QTableView, _HalWidgetBase):
|
||||
def __init__(self, parent=None):
|
||||
super(ToolOffsetView, self).__init__(parent)
|
||||
self.setAlternatingRowColors(True)
|
||||
|
||||
self.filename = INFO.PARAMETER_FILE
|
||||
self.axisletters = ["x", "y", "z", "a", "b", "c", "u", "v", "w"]
|
||||
self.editing_flag = False
|
||||
self.current_system = None
|
||||
self.current_tool = 0
|
||||
self.setEnabled(False)
|
||||
self.dialog_code = 'CALCULATOR'
|
||||
self.text_dialog_code = 'KEYBOARD'
|
||||
self.setIconSize(QSize(32,32))
|
||||
self._last = 0
|
||||
|
||||
# create table
|
||||
self.createAllView()
|
||||
|
||||
def _hal_init(self):
|
||||
self.delay = 0
|
||||
STATUS.connect('all-homed', lambda w: self.setEnabled(True))
|
||||
STATUS.connect('not-all-homed', lambda w, axis: 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(False))
|
||||
STATUS.connect('metric-mode-changed', lambda w, data: self.metricMode(data))
|
||||
STATUS.connect('diameter-mode', lambda w, data: self.diameterMode(data))
|
||||
STATUS.connect('tool-in-spindle-changed', lambda w, data: self.currentTool(data))
|
||||
STATUS.connect('general',self.return_value)
|
||||
|
||||
conversion = {5:"Y", 6:'Y', 7:"Z", 8:'Z', 9:"A", 10:"B", 11:"C", 12:"U", 13:"V", 14:"W"}
|
||||
for num, let in conversion.items():
|
||||
if let in (INFO.AVAILABLE_AXES):
|
||||
continue
|
||||
self.hideColumn(num)
|
||||
if not INFO.MACHINE_IS_LATHE:
|
||||
for i in (4,6,8,16,17,18):
|
||||
self.hideColumn(i)
|
||||
|
||||
def currentTool(self, data):
|
||||
self.current_tool = data
|
||||
|
||||
def metricMode(self, state):
|
||||
self.tablemodel.metricDisplay(state)
|
||||
self.update()
|
||||
|
||||
def diameterMode(self, state):
|
||||
self.tablemodel.diameterDisplay(state)
|
||||
self.update()
|
||||
|
||||
def createAllView(self):
|
||||
styledItemDelegate=QStyledItemDelegate()
|
||||
styledItemDelegate.setItemEditorFactory(ItemEditorFactory())
|
||||
self.setItemDelegate(styledItemDelegate)
|
||||
|
||||
# create the view
|
||||
self.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
#self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
|
||||
# set the table model
|
||||
self.tablemodel = MyTableModel(self)
|
||||
self.setModel(self.tablemodel)
|
||||
self.clicked.connect(self.showSelection)
|
||||
#self.dataChanged.connect(self.selection_changed)
|
||||
|
||||
# set the minimum size
|
||||
self.setMinimumSize(100, 100)
|
||||
|
||||
# set horizontal header properties
|
||||
hh = self.horizontalHeader()
|
||||
# auto adjust to contents
|
||||
hh.setSectionResizeMode(QHeaderView.ResizeToContents)
|
||||
|
||||
hh.setStretchLastSection(True)
|
||||
hh.setSortIndicator(1,Qt.AscendingOrder)
|
||||
|
||||
vh = self.verticalHeader()
|
||||
vh.setVisible(False)
|
||||
|
||||
# set column width to fit contents
|
||||
self.resizeColumnsToContents()
|
||||
|
||||
# set row height
|
||||
self.resizeRowsToContents()
|
||||
|
||||
# enable sorting
|
||||
self.setSortingEnabled(True)
|
||||
|
||||
def showSelection(self, item):
|
||||
cellContent = item.data()
|
||||
text = cellContent
|
||||
LOG.debug('Text: {}, Row: {}, Column: {}'.format(text, item.row(), item.column()))
|
||||
sf = "You clicked on {}".format(text)
|
||||
# display in title bar for convenience
|
||||
self.setWindowTitle(sf)
|
||||
# row 0 is not editable (checkbox position)
|
||||
# column 19 is the descriptive text column
|
||||
if item.column() == 19:
|
||||
self.callTextDialog(text,item)
|
||||
elif item.column() <19 and item.column() > 0:
|
||||
self.callDialog(text,item)
|
||||
|
||||
# alphanumerical
|
||||
def callTextDialog(self, text,item):
|
||||
text = self.tablemodel.arraydata[item.row()][19]
|
||||
tool = self.tablemodel.arraydata[item.row()][1]
|
||||
mess = {'NAME':self.text_dialog_code,'ID':'%s__' % self.objectName(),
|
||||
'PRELOAD':text, 'TITLE':'Tool {} Description Entry'.format(tool),
|
||||
'ITEM':item}
|
||||
LOG.debug('message sent:{}'.format (mess))
|
||||
STATUS.emit('dialog-request', mess)
|
||||
|
||||
# numerical only
|
||||
def callDialog(self, text, item, next=False):
|
||||
axis = self.tablemodel.headerdata[item.column()]
|
||||
tool = self.tablemodel.arraydata[item.row()][1]
|
||||
|
||||
mess = {'NAME':self.dialog_code,'ID':'%s__' % self.objectName(),
|
||||
'PRELOAD':float(text),
|
||||
'TITLE':'Tool {} Offset of {},{}'.format(tool, axis,text),
|
||||
'ITEM':item,
|
||||
'NEXT':next,
|
||||
'WIDGETCYCLE': True}
|
||||
LOG.debug('message sent:{}'.format (mess))
|
||||
STATUS.emit('dialog-request', mess)
|
||||
|
||||
|
||||
# process the STATUS return message
|
||||
def return_value(self, w, message):
|
||||
num = message['RETURN']
|
||||
code = bool(message.get('ID') == '%s__'% self.objectName())
|
||||
name = bool(message.get('NAME') == self.dialog_code)
|
||||
name2 = bool(message.get('NAME') == self.text_dialog_code)
|
||||
item = message.get('ITEM')
|
||||
next = message.get('NEXT', False)
|
||||
back = message.get('BACK', False)
|
||||
|
||||
if code:
|
||||
LOG.debug('message returned:{}'.format (message))
|
||||
if code and name and num is not None:
|
||||
self.tablemodel.setData(item, num, None)
|
||||
elif code and name2 and num is not None:
|
||||
self.tablemodel.setData(item, num, None)
|
||||
|
||||
# request for next input widget to right or left
|
||||
if code and name:
|
||||
|
||||
if next:
|
||||
self.right()
|
||||
|
||||
newobj = self.currentIndex()
|
||||
# if we selected the text column, move back
|
||||
if newobj.column() == 19:
|
||||
self.left()
|
||||
newobj = self.currentIndex()
|
||||
cellContent = newobj.data()
|
||||
text = cellContent
|
||||
|
||||
# update the screen
|
||||
QApplication.processEvents()
|
||||
|
||||
# update the dialog
|
||||
self.callDialog(text,newobj,True)
|
||||
|
||||
elif back:
|
||||
self.left()
|
||||
|
||||
newobj = self.currentIndex()
|
||||
# if we selected the checkbox column, move forward
|
||||
if newobj.column() == 0:
|
||||
self.right()
|
||||
newobj = self.currentIndex()
|
||||
|
||||
newobj = self.currentIndex()
|
||||
cellContent = newobj.data()
|
||||
text = cellContent
|
||||
|
||||
# update the screen
|
||||
QApplication.processEvents()
|
||||
|
||||
# update the dialog
|
||||
self.callDialog(text,newobj,True)
|
||||
|
||||
#############################################################
|
||||
|
||||
def dataChanged(self, new, old, roles):
|
||||
self.editing_flag = True
|
||||
row = new.row()
|
||||
col = new.column()
|
||||
data = self.tablemodel.data(new)
|
||||
#print('Entered data:', data, row,col)
|
||||
# now update linuxcnc to the change
|
||||
try:
|
||||
if STATUS.is_status_valid():
|
||||
#for i in self.tablemodel.arraydata:
|
||||
# LOG.debug("2>>> = {}".format(i))
|
||||
error = TOOL.SAVE_TOOLFILE(TOOL.CONVERT_TO_STANDARD_TYPE(self.tablemodel.arraydata))
|
||||
if error:
|
||||
raise
|
||||
ACTION.RECORD_CURRENT_MODE()
|
||||
ACTION.CALL_MDI('g43')
|
||||
ACTION.RESTORE_RECORDED_MODE()
|
||||
STATUS.emit('reload-display')
|
||||
#self.tablemodel.update()
|
||||
#self.resizeColumnsToContents()
|
||||
except Exception as e:
|
||||
LOG.exception("offsetpage widget error: MDI call error", exc_info=e)
|
||||
self.editing_flag = False
|
||||
|
||||
def add_tool(self):
|
||||
if not STATUS.is_auto_running():
|
||||
LOG.debug('add tool request')
|
||||
TOOL.ADD_TOOL()
|
||||
|
||||
def delete_tools(self):
|
||||
if not STATUS.is_auto_running():
|
||||
LOG.debug('delete tools request')
|
||||
dtools = self.tablemodel.listCheckedTools()
|
||||
if dtools:
|
||||
error = TOOL.DELETE_TOOLS(dtools)
|
||||
|
||||
def get_checked_list(self):
|
||||
return self.tablemodel.listCheckedTools()
|
||||
|
||||
def set_all_unchecked(self):
|
||||
self.tablemodel.uncheckAllTools()
|
||||
|
||||
# This function uses the color name (string); setProperty
|
||||
# expects a QColor object
|
||||
def highlight(self, color):
|
||||
self.setProperty('styleColorHighlight', QColor(color))
|
||||
|
||||
# This function uses the color name (string); calling setProperty
|
||||
# expects a QColor object
|
||||
def selected(self, color):
|
||||
self.setProperty('styleColorSelection', QColor(color))
|
||||
|
||||
# external controls
|
||||
@Slot(float)
|
||||
@Slot(int)
|
||||
def scroll(self, data):
|
||||
if data > self._last:
|
||||
self.right()
|
||||
elif data < self._last:
|
||||
self.right()
|
||||
self._last = data
|
||||
|
||||
# moves the selection up
|
||||
@Slot()
|
||||
def up(self):
|
||||
cr = self.currentIndex().row()
|
||||
# state of checkbox ie. is this row selected?
|
||||
# if selected, move horizontally
|
||||
state = self.model().arraydata[cr][0].isChecked()
|
||||
if state:
|
||||
self.right()
|
||||
return
|
||||
else:
|
||||
self.setCurrentIndex(self.moveCursor(QAbstractItemView.CursorAction.MoveUp,Qt.NoModifier))
|
||||
|
||||
# moves the selection down
|
||||
@Slot()
|
||||
def down(self):
|
||||
cr = self.currentIndex().row()
|
||||
# state of checkbox ie. is this row selected?
|
||||
# if selected, move horizontally
|
||||
state = self.model().arraydata[cr][0].isChecked()
|
||||
if state:
|
||||
self.left()
|
||||
return
|
||||
else:
|
||||
self.setCurrentIndex(self.moveCursor(QAbstractItemView.CursorAction.MoveDown,Qt.NoModifier))
|
||||
|
||||
def left(self):
|
||||
self.setCurrentIndex(self.moveCursor(QAbstractItemView.CursorAction.MoveLeft,Qt.NoModifier))
|
||||
|
||||
def right(self):
|
||||
self.setCurrentIndex(self.moveCursor(QAbstractItemView.CursorAction.MoveRight,Qt.NoModifier))
|
||||
|
||||
def toggleCurrent(self):
|
||||
self.model().toggle(self.currentIndex().row())
|
||||
|
||||
#########################################################################
|
||||
# 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
|
||||
#
|
||||
########################################################################
|
||||
|
||||
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 = 'CALCULATOR'
|
||||
dialog_code_string = Property(str, get_dialog_code, set_dialog_code, reset_dialog_code)
|
||||
|
||||
def set_keyboard_code(self, data):
|
||||
self.text_dialog_code = data
|
||||
def get_keyboard_code(self):
|
||||
return self.text_dialog_code
|
||||
def reset_keyboard_code(self):
|
||||
self.text_dialog_code = 'KEYBOARD'
|
||||
text_dialog_code_string = Property(str, get_keyboard_code, set_keyboard_code, reset_keyboard_code)
|
||||
|
||||
def setmetrictemplate(self, data):
|
||||
self.tablemodel.metric_text_template = data
|
||||
def getmetrictemplate(self):
|
||||
return self.tablemodel.metric_text_template
|
||||
def resetmetrictemplate(self):
|
||||
self.tablemodel.metric_text_template = '%10.3f'
|
||||
metric_template = Property(str, getmetrictemplate, setmetrictemplate, resetmetrictemplate)
|
||||
|
||||
def setimperialtexttemplate(self, data):
|
||||
self.tablemodel.imperial_text_template = data
|
||||
def getimperialtexttemplate(self):
|
||||
return self.tablemodel.imperial_text_template
|
||||
def resetimperialtexttemplate(self):
|
||||
self.tablemodel.imperial_text_template = '%9.4f'
|
||||
imperial_template = Property(str, getimperialtexttemplate, setimperialtexttemplate, resetimperialtexttemplate)
|
||||
|
||||
def getColorHighlight(self):
|
||||
return QColor(self.tablemodel._highlightcolor)
|
||||
def setColorHighlight(self, value):
|
||||
self.tablemodel._highlightcolor = value.name()
|
||||
#self.tablemodel.layoutChanged.emit()
|
||||
styleColorHighlight = Property(QColor, getColorHighlight, setColorHighlight)
|
||||
|
||||
def getColorSelection(self):
|
||||
return QColor(self.tablemodel._selectedcolor)
|
||||
def setColorSelection(self, value):
|
||||
self.tablemodel._selectedcolor = value.name()
|
||||
#self.tablemodel.layoutChanged.emit()
|
||||
styleColorSelection = Property(QColor, getColorSelection, setColorSelection)
|
||||
|
||||
#########################################
|
||||
# custom model
|
||||
#########################################
|
||||
class MyTableModel(QAbstractTableModel):
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Args:
|
||||
datain: a list of lists\n
|
||||
headerdata: a list of strings
|
||||
"""
|
||||
super(MyTableModel, self).__init__(parent)
|
||||
self.text_template = '%.4f'
|
||||
self.metric_text_template = '%10.3f'
|
||||
self.zero_text_template = '%10.1f'
|
||||
self.imperial_text_template = '%9.4f'
|
||||
self.degree_text_template = '%10.1f'
|
||||
self.metric_display = False
|
||||
self.diameter_display = False
|
||||
self._highlightcolor = '#00ffff'
|
||||
self._selectedcolor = '#00ff00'
|
||||
self.headerdata = ['','tool','pocket','X','X Wear', 'Y', 'Y Wear', 'Z', 'Z Wear', 'A', 'B', 'C', 'U', 'V', 'W', 'Diameter', 'Front Angle', 'Back Angle','Orient','Comment']
|
||||
if INFO.MACHINE_IS_LATHE:
|
||||
self.headerdata[2] = 'Stn'
|
||||
self.vheaderdata = []
|
||||
self.arraydata = [[0, 0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0,'No Tool']]
|
||||
STATUS.connect('toolfile-stale',lambda o, d: self.update(d))
|
||||
self.update(None)
|
||||
|
||||
def metricDisplay(self, state):
|
||||
self.metric_display = state
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def diameterDisplay(self, state):
|
||||
self.diameter_display = state
|
||||
self.layoutChanged.emit()
|
||||
|
||||
# make a list of all the checked tools
|
||||
def listCheckedTools(self):
|
||||
checkedlist = []
|
||||
for row in self.arraydata:
|
||||
if row[0].isChecked():
|
||||
checkedlist.append(row[1])
|
||||
return checkedlist
|
||||
|
||||
def uncheckAllTools(self):
|
||||
for row in self.arraydata:
|
||||
if row[0].isChecked():
|
||||
row[0].setChecked(False)
|
||||
|
||||
def toggle(self, row):
|
||||
item = self.arraydata[row][0]
|
||||
newState = (not item.isChecked())
|
||||
self.uncheckAllTools()
|
||||
item.setChecked(newState)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
# update the internal array from STATUS's toolfile read array
|
||||
# we make sure the first array is switched to a QCheckbox widget
|
||||
def update(self, models):
|
||||
data = TOOL.CONVERT_TO_WEAR_TYPE(models)
|
||||
if data in (None, []):
|
||||
data = [[QCheckBox(),0, 0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0,'No Tool']]
|
||||
for line in data:
|
||||
if line[0] != QCheckBox:
|
||||
line[0] = QCheckBox()
|
||||
self.arraydata = data
|
||||
self.layoutChanged.emit()
|
||||
|
||||
# Returns the number of rows under the given parent.
|
||||
# When the parent is valid it means that rowCount is
|
||||
# returning the number of children of parent.
|
||||
#
|
||||
# Note: When implementing a table based model, rowCount()
|
||||
# should return 0 when the parent is valid.
|
||||
def rowCount(self, parent):
|
||||
return len(self.arraydata)
|
||||
|
||||
# Returns the number of columns for the children of the given parent.
|
||||
# Note: When implementing a table based model, columnCount() should
|
||||
# return 0 when the parent is valid.
|
||||
def columnCount(self, parent):
|
||||
if len(self.arraydata) > 0:
|
||||
return len(self.arraydata[0])
|
||||
return 0
|
||||
|
||||
# Returns the data stored under the given role for the item referred to by the index.
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
|
||||
if role == Qt.EditRole:
|
||||
return self.arraydata[index.row()][index.column()]
|
||||
|
||||
elif role == Qt.DecorationRole and index.column() == 18:
|
||||
value = self.arraydata[index.row()][index.column()]
|
||||
return QIcon(os.path.join(ICONPATH, "tool_pos_{}.png".format(value)))
|
||||
|
||||
elif role == Qt.DisplayRole:
|
||||
value = self.arraydata[index.row()][index.column()]
|
||||
col = index.column()
|
||||
if isinstance(value, float):
|
||||
if value == 0.0:
|
||||
tmpl = lambda s: self.zero_text_template % s
|
||||
return tmpl(value)
|
||||
elif col in(16,17):
|
||||
tmpl = lambda s: self.degree_text_template % s
|
||||
return tmpl(value)
|
||||
elif self.metric_display:
|
||||
tmpl = lambda s: self.metric_text_template % s
|
||||
else:
|
||||
tmpl = lambda s: self.imperial_text_template % s
|
||||
if self.metric_display != INFO.MACHINE_IS_METRIC:
|
||||
value = INFO.convert_units(value)
|
||||
if col in(3,4):
|
||||
if self.diameter_display:
|
||||
value *=2
|
||||
self.headerdata[3] = 'X D'
|
||||
self.headerdata[4] = 'X Wear D'
|
||||
else:
|
||||
self.headerdata[3] = 'X R'
|
||||
self.headerdata[4] = 'X Wear R'
|
||||
return tmpl(value)
|
||||
|
||||
if isinstance(value, str):
|
||||
return '%s' % value
|
||||
# Default (anything not captured above: e.g. int)
|
||||
return value
|
||||
|
||||
elif role == Qt.BackgroundRole:
|
||||
value = self.arraydata[index.row()][index.column()]
|
||||
if (isinstance(value, int) or isinstance(value, float) or
|
||||
isinstance(value, str), isinstance(value, QCheckBox)):
|
||||
if self.arraydata[index.row()][1] == self.parent().current_tool:
|
||||
return QColor(self._highlightcolor)
|
||||
elif self.arraydata[index.row()][0].isChecked():
|
||||
return QColor(self._selectedcolor)
|
||||
else:
|
||||
return None
|
||||
|
||||
elif role == Qt.CheckStateRole:
|
||||
if index.column() == 0:
|
||||
# print(">>> data() row,col = %d, %d" % (index.row(), index.column()))
|
||||
if self.arraydata[index.row()][index.column()].isChecked():
|
||||
return Qt.Checked
|
||||
else:
|
||||
return Qt.Unchecked
|
||||
|
||||
elif role == Qt.ForegroundRole:
|
||||
value = self.arraydata[index.row()][index.column()]
|
||||
|
||||
if ((isinstance(value, int) or isinstance(value, float))
|
||||
and value < 0 ):
|
||||
return QColor('red')
|
||||
|
||||
return None
|
||||
|
||||
|
||||
# Returns the item flags for the given index.
|
||||
def flags(self, index):
|
||||
if not index.isValid():
|
||||
return None
|
||||
if index.column() == 0:
|
||||
return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable
|
||||
else:
|
||||
return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
|
||||
|
||||
# Sets the role data for the item at index to value.
|
||||
# Returns true if successful; otherwise returns false.
|
||||
# The dataChanged() signal should be emitted if the data was successfully set.
|
||||
# these column numbers correspond to our included wear columns
|
||||
# it will be converted when saved
|
||||
def setData(self, index, value, role):
|
||||
col = index.column()
|
||||
if not index.isValid():
|
||||
LOG.error(">>> index not valid {}".format(index))
|
||||
return False
|
||||
LOG.debug("original value:{}".format(self.arraydata[index.row()][col]))
|
||||
LOG.debug(">>> setData() role = {}".format(role))
|
||||
LOG.debug(">>> setData() column() = {}".format(col))
|
||||
if role == Qt.CheckStateRole and index.column() == 0:
|
||||
#print(">>> setData() role = ", role)
|
||||
#print(">>> setData() index.column() = ", index.column())
|
||||
if value == Qt.Checked:
|
||||
self.uncheckAllTools()
|
||||
self.arraydata[index.row()][index.column()].setChecked(True)
|
||||
#self.arraydata[index.row()][index.column()].setText("Delete")
|
||||
#print 'selected',self.arraydata[index.row()][1]
|
||||
else:
|
||||
self.arraydata[index.row()][index.column()].setChecked(False)
|
||||
#self.arraydata[index.row()][index.column()].setText("Un")
|
||||
# don't emit dataChanged - return right away
|
||||
self.parent().reset()
|
||||
return True
|
||||
|
||||
|
||||
try:
|
||||
if col in (1,2,18): # tool, pocket, orientation
|
||||
v = int(value)
|
||||
elif col == 19:
|
||||
v = str(value) # comment
|
||||
else:
|
||||
v = float(value)
|
||||
if self.metric_display:
|
||||
v = INFO.convert_metric_to_machine(value)
|
||||
else:
|
||||
v = INFO.convert_imperial_to_machine(value)
|
||||
if col in(3,4) and self.diameter_display:
|
||||
v /=2
|
||||
self.arraydata[index.row()][col] = v
|
||||
except:
|
||||
LOG.error("Invalid data type in row {} column:{} ".format(index.row(), col))
|
||||
return False
|
||||
LOG.debug(">>> setData() value = {} ".format(value))
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
# Returns the data for the given role and section in the header with the specified orientation.
|
||||
# For horizontal headers, the section number corresponds to the column number.
|
||||
# Similarly, for vertical headers, the section number corresponds to the row number.
|
||||
def headerData(self, col, orientation, role):
|
||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
|
||||
return self.headerdata[col]
|
||||
if orientation != Qt.Horizontal and role == Qt.DisplayRole:
|
||||
return ''
|
||||
return None
|
||||
|
||||
# Sorts the model by column in the given order.
|
||||
def sort(self, Ncol, order):
|
||||
"""
|
||||
Sort table by given column number.
|
||||
"""
|
||||
# don't sort checkbox column
|
||||
if Ncol != 0:
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
self.arraydata = sorted(self.arraydata, key=operator.itemgetter(Ncol))
|
||||
if order == Qt.DescendingOrder:
|
||||
self.arraydata.reverse()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
from qtpy.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
w = ToolOffsetView()
|
||||
w.setEnabled(True)
|
||||
w._hal_init()
|
||||
w.highlight('lightblue')
|
||||
#w.setProperty('styleColorHighlight',QColor('purple'))
|
||||
w.show()
|
||||
sys.exit(app.exec())
|
||||
Reference in New Issue
Block a user