Import LinuxCNC source tree

This commit is contained in:
Wang Dequan
2026-08-20 06:17:39 +08:00
commit 2c814634c3
9429 changed files with 10556013 additions and 0 deletions

View File

@@ -0,0 +1,418 @@
#!/usr/bin/env python3
#
# QTVcp Widget - Machine Log
# Copyright (c) 2017 Chris Morley with additions by Steve Richardson
#
# 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 os
import hashlib
import time
from qtpy.QtWidgets import QWidget, QTextEdit, QTableWidget, QTableWidgetItem, QVBoxLayout
from qtpy.QtCore import QFile, Property
import qtpy.QtWidgets as QtWidgets
from qtpy.QtGui import QColor
from qtvcp.widgets.widget_baseclass import _HalWidgetBase
from qtvcp.core import Status, Info, Action
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__)
class MachineLog(QWidget, _HalWidgetBase):
def __init__(self, parent=None):
super(MachineLog, self).__init__(parent)
self._delay = 0
self._hash_code = None
self._log_on = True
self._machine_log = True
self._machine_log_severity = False
self._integrator_log = False
self._critical_fg_color = QColor(255, 255, 255)
self._critical_bg_color = QColor(255, 0, 0)
self._error_fg_color = QColor(255, 0, 0)
self._error_bg_color = QColor(255,255,255)
self._warning_fg_color = QColor(255, 255, 0)
self._warning_bg_color = QColor(0, 0, 0)
self._debug_fg_color = QColor(128, 128, 128)
self._debug_bg_color = QColor(255, 255, 255)
self._info_fg_color = QColor(0, 0, 0)
self._info_bg_color = QColor(255, 255, 255)
self.integratorPath = os.path.expanduser(INFO.QTVCP_LOG_HISTORY_PATH)
self.machineLogPath = os.path.expanduser(INFO.MACHINE_LOG_HISTORY_PATH)
self.logText = QTextEdit(self)
self.logTable = QTableWidget(self)
layout = QVBoxLayout(self)
layout.addWidget(self.logText)
layout.addWidget(self.logTable)
self.setLayout(layout)
self.logTable.setColumnCount(3)
self.logTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.logTable.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.logTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.logTable.setShowGrid(False)
self.logTable.setSortingEnabled(False)
horizontalHeader = self.logTable.horizontalHeader()
horizontalHeader.resizeSection(0, 100)
horizontalHeader.resizeSection(1, 100)
horizontalHeader.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
horizontalHeader.setVisible(False)
verticalHeader = self.logTable.verticalHeader()
verticalHeader.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
verticalHeader.setVisible(False)
def _hal_init(self):
if self._machine_log:
STATUS.connect('machine-log-changed',lambda w: self.loadLog())
self.logTable.hide()
self.logText.show()
elif self._machine_log_severity:
STATUS.connect('update-machine-log', lambda w, d, o: self.updateMachineLog(d, o))
self.logTable.show()
self.logText.hide()
elif self._integrator_log:
STATUS.connect('periodic', self._periodicCheck)
self.logTable.hide()
self.logText.show()
def _periodicCheck(self, w):
if self._delay < 9:
self._delay += 1
return
if STATUS.is_status_valid() == False:
return
self._delay = 0
m1 = self.md5sum(self.integratorPath)
if m1 and self._hash_code != m1:
self._hash_code = m1
self.loadIntegratorLog()
# create a hash code
def md5sum(self,filename):
try:
f = open(filename, "rb")
except:
return None
else:
return hashlib.md5(f.read()).hexdigest()
def remove_options(self, option, to_remove):
options = option.split(',')
options = [opt for opt in options if opt not in to_remove]
return ','.join(options)
def updateMachineLog(self, message, option):
if option == 'DELETE':
self.clear()
return
if option == 'ON':
self._log_on = True
return
if option == 'OFF':
self._log_on = False
return
if self._log_on != True:
return
if message:
if option is None: option = ''
if 'DATE' in option:
dateItem = QTableWidgetItem(time.strftime("%a, %b %d %Y %X"))
else:
dateItem = QTableWidgetItem(time.strftime("%H:%M:%S"))
option = self.remove_options(option, ['DATE', 'TIME', 'INITIAL'])
severityItem = QTableWidgetItem(option.strip())
msgItem = QTableWidgetItem(message.strip())
if 'DEBUG' in option:
msgItem.setForeground(self._debug_fg_color)
dateItem.setForeground(self._debug_fg_color)
severityItem.setForeground(self._debug_fg_color)
msgItem.setBackground(self._debug_bg_color)
dateItem.setBackground(self._debug_bg_color)
severityItem.setBackground(self._debug_bg_color)
elif 'SUCCESS' in option:
msgItem.setForeground(QColor(0, 128, 0))
dateItem.setForeground(QColor(0, 128, 0))
severityItem.setForeground(QColor(0, 128, 0))
elif 'WARNING' in option:
msgItem.setForeground(self._warning_fg_color)
dateItem.setForeground(self._warning_fg_color)
severityItem.setForeground(self._warning_fg_color)
msgItem.setBackground(self._warning_bg_color)
dateItem.setBackground(self._warning_bg_color)
severityItem.setBackground(self._warning_bg_color)
if self.QTVCP_INSTANCE_.OPTIONS_.play_sounds:
ACTION.PLAY_WARNING()
elif 'ERROR' in option:
msgItem.setForeground(self._error_fg_color)
dateItem.setForeground(self._error_fg_color)
severityItem.setForeground(self._error_fg_color)
msgItem.setBackground(self._error_bg_color)
dateItem.setBackground(self._error_bg_color)
severityItem.setBackground(self._error_bg_color)
if self.QTVCP_INSTANCE_.OPTIONS_.play_sounds:
ACTION.PLAY_ATTENTION()
elif 'CRITICAL' in option:
msgItem.setForeground(self._critical_fg_color)
dateItem.setForeground(self._critical_fg_color)
severityItem.setForeground(self._critical_fg_color)
msgItem.setBackground(self._critical_bg_color)
dateItem.setBackground(self._critical_bg_color)
severityItem.setBackground(self._critical_bg_color)
if self.QTVCP_INSTANCE_.OPTIONS_.play_sounds:
ACTION.PLAY_ERROR()
else:
msgItem.setForeground(self._info_fg_color)
dateItem.setForeground(self._info_fg_color)
severityItem.setForeground(self._info_fg_color)
msgItem.setBackground(self._info_bg_color)
dateItem.setBackground(self._info_bg_color)
severityItem.setBackground(self._info_bg_color)
self.logTable.insertRow(self.logTable.rowCount())
self.logTable.setItem(self.logTable.rowCount()-1, 0, dateItem)
self.logTable.setItem(self.logTable.rowCount()-1, 1, severityItem)
self.logTable.setItem(self.logTable.rowCount()-1, 2, msgItem)
self.logTable.scrollToBottom()
def loadLog(self):
file = QFile(self.machineLogPath)
file.open(QFile.ReadOnly)
logText = file.readAll()
file.close()
self.logText.setPlainText(str(logText, encoding='utf8'))
# scroll down to show last entry
self.logText.verticalScrollBar().setSliderPosition(self.logText.verticalScrollBar().maximum())
def loadIntegratorLog(self):
file = QFile(self.integratorPath)
file.open(QFile.ReadOnly)
logText = file.readAll()
file.close()
if str(logText, encoding='utf8') == "":
self.logText.setPlainText('No Logging found. Is QtVcp in info, debugging or verbose mode (-i, -d or -v)?')
return
self.logText.setHtml(str(logText, encoding='utf8'))
# scroll down to show last entry
self.logText.verticalScrollBar().setSliderPosition(self.logText.verticalScrollBar().maximum())
def showEvent(self, ev):
self.scrollToBottom()
def scrollToBottom(self):
# scroll down to show last entry
self.logText.verticalScrollBar().setSliderPosition(self.logText.verticalScrollBar().maximum())
self.logTable.scrollToBottom()
def hideCursor(self):
self.logText.setCursorWidth(0)
def getLogText(self):
if self._machine_log_severity:
return self.readTableData()
else:
return self.logText.toPlainText()
def clear(self):
self.logTable.clearContents()
self.logTable.setRowCount(0)
self.logText.setPlainText('')
def readTableData(self):
data = ''
for row in range(self.logTable.rowCount()):
row_data = []
for col in range(self.logTable.columnCount()):
item = self.logTable.item(row, col).text()
if col == 1:
# pad the severity column for ease of reading
row_data.append("{:^10}".format(item))
elif item != '':
row_data.append(item)
data += ' '.join(row_data)
data +='\n'
return data
################## properties ###################
def _toggle_properties(self, picked):
data = ('machine_log', 'machine_log_severity', 'integrator_log')
for i in data:
if not i == picked:
self[i+'_option'] = False
def set_machine_log(self, value):
self._machine_log = value
if value:
self._toggle_properties('machine_log')
def get_machine_log(self):
return self._machine_log
def reset_machine_log(self):
self._machine_log = True
machine_log_option = Property(bool, get_machine_log, set_machine_log, reset_machine_log)
def set_machine_log_severity(self, value):
self._machine_log_severity = value
if value:
self._toggle_properties('machine_log_severity')
def get_machine_log_severity(self):
return self._machine_log_severity
def reset_machine_log_severity(self):
self._machine_log_severity = False
machine_log_severity_option = Property(bool, get_machine_log_severity, set_machine_log_severity, reset_machine_log_severity)
def set_integrator_log(self, value):
self._integrator_log = value
if value:
self._toggle_properties('integrator_log')
def get_integrator_log(self):
return self._integrator_log
def reset_integrator_log(self):
self._integrator_log = False
integrator_log_option = Property(bool, get_integrator_log, set_integrator_log, reset_integrator_log)
def set_critical_fg_color(self, value):
self._critical_fg_color = value
def get_critical_fg_color(self):
return self._critical_fg_color
def reset_critical_fg_color(self):
self._critical_fg_color = QColor(255, 255, 255)
critical_fg_color_option = Property(QColor, get_critical_fg_color, set_critical_fg_color, reset_critical_fg_color)
def set_critical_bg_color(self, value):
self._critical_bg_color = value
def get_critical_bg_color(self):
return self._critical_bg_color
def reset_critical_bg_color(self):
self._critical_bg_color = QColor(255, 0, 0)
critical_bg_color_option = Property(QColor, get_critical_bg_color, set_critical_bg_color, reset_critical_bg_color)
def set_error_fg_color(self, value):
self._error_fg_color = value
def get_error_fg_color(self):
return self._error_fg_color
def reset_error_fg_color(self):
self._error_fg_color = QColor(255, 0, 0)
error_fg_color_option = Property(QColor, get_error_fg_color, set_error_fg_color, reset_error_fg_color)
def set_error_bg_color(self, value):
self._error_bg_color = value
def get_error_bg_color(self):
return self._error_bg_color
def reset_error_bg_color(self):
self._error_bg_color = QColor(255, 255, 255)
error_bg_color_option = Property(QColor, get_error_bg_color, set_error_bg_color, reset_error_bg_color)
def set_warning_fg_color(self, value):
self._warning_fg_color = value
def get_warning_fg_color(self):
return self._warning_fg_color
def reset_warning_fg_color(self):
self._warning_fg_color = QColor(255, 255, 0)
warning_fg_color_option = Property(QColor, get_warning_fg_color, set_warning_fg_color, reset_warning_fg_color)
def set_warning_bg_color(self, value):
self._warning_bg_color = value
def get_warning_bg_color(self):
return self._warning_bg_color
def reset_warning_bg_color(self):
self._warning_bg_color = QColor(255, 255, 255)
warning_bg_color_option = Property(QColor, get_warning_bg_color, set_warning_bg_color, reset_warning_bg_color)
def set_debug_fg_color(self, value):
self._debug_fg_color = value
def get_debug_fg_color(self):
return self._debug_fg_color
def reset_debug_fg_color(self):
self._debug_fg_color = QColor(128, 128, 128)
debug_fg_color_option = Property(QColor, get_debug_fg_color, set_debug_fg_color, reset_debug_fg_color)
def set_debug_bg_color(self, value):
self._debug_bg_color = value
def get_debug_bg_color(self):
return self._debug_bg_color
def reset_debug_bg_color(self):
self._debug_bg_color = QColor(255, 255, 255)
debug_bg_color_option = Property(QColor, get_debug_bg_color, set_debug_bg_color, reset_debug_bg_color)
def set_info_fg_color(self, value):
self._info_fg_color = value
def get_info_fg_color(self):
return self._info_fg_color
def reset_info_fg_color(self):
self._info_fg_color = QColor(0, 0, 0)
info_fg_color_option = Property(QColor, get_info_fg_color, set_info_fg_color, reset_info_fg_color)
def set_info_bg_color(self, value):
self._info_bg_color = value
def get_info_bg_color(self):
return self._info_bg_color
def reset_info_bg_color(self):
self._info_bg_color = QColor(255, 255, 255)
info_bg_color_option = Property(QColor, get_info_bg_color, set_info_bg_color, reset_info_bg_color)
##############################
# required class boiler code #
##############################
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
# for testing without editor:
def main():
import sys
from qtpy.QtWidgets import QApplication
app = QApplication(sys.argv)
widget = MachineLog()
widget.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()