CAM: Show line numbers in export gcode dialog

This commit is contained in:
tarman3
2025-09-12 10:38:52 +03:00
parent 8c8b26ee4b
commit 0e0f948d71
23 changed files with 117 additions and 28 deletions

View File

@@ -93,6 +93,7 @@ SET(PathPythonMain_SRCS
SET(PathPythonMainGui_SRCS
Path/Main/Gui/__init__.py
Path/Main/Gui/Camotics.py
Path/Main/Gui/Editor.py
Path/Main/Gui/Fixture.py
Path/Main/Gui/Inspect.py
Path/Main/Gui/Job.py

View File

@@ -0,0 +1,83 @@
from PySide.QtWidgets import QWidget, QPlainTextEdit
from PySide.QtGui import QPainter, QFont
from PySide.QtCore import Qt, QRect, QSize
class LineNumberArea(QWidget):
def __init__(self, editor):
super().__init__(editor)
self.editor = editor
def sizeHint(self):
return QSize(self.editor.fontMetrics().horizontalAdvance("999") + 4, 0)
def paintEvent(self, event):
painter = QPainter(self)
painter.fillRect(event.rect(), Qt.black)
font = QFont()
font.setFamily(self.editor.font().family())
font.setFixedPitch(self.editor.font().fixedPitch())
font.setPointSize(self.editor.font().pointSize())
painter.setFont(font)
block = self.editor.firstVisibleBlock()
blockNumber = block.blockNumber()
top = self.editor.blockBoundingGeometry(block).translated(self.editor.contentOffset()).top()
bottom = top + self.editor.blockBoundingRect(block).height()
while block.isValid() and top <= event.rect().bottom():
if block.isVisible() and bottom >= event.rect().top():
number = str(blockNumber + 1)
painter.setPen(Qt.gray)
painter.drawText(
-6,
int(top),
self.width(),
self.editor.fontMetrics().height(),
Qt.AlignRight,
number,
)
block = block.next()
top = bottom
bottom = top + self.editor.blockBoundingRect(block).height()
blockNumber += 1
class CodeEditor(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.lineNumberArea = LineNumberArea(self)
self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
self.updateRequest.connect(self.updateLineNumberArea)
self.verticalScrollBar().valueChanged.connect(self.lineNumberArea.update) # Simple update
self.updateLineNumberAreaWidth(0) # Initial call
def lineNumberAreaWidth(self):
digits = 2
max_value = max(1, self.blockCount())
while max_value >= 10:
max_value /= 10
digits += 1
space = 3 + self.fontMetrics().horizontalAdvance("9") * digits
return space
def updateLineNumberAreaWidth(self, newBlockCount):
self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
def updateLineNumberArea(self, rect, dy):
if dy:
self.lineNumberArea.scroll(0, dy)
else:
self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height())
if rect.contains(self.viewport().rect()):
self.updateLineNumberAreaWidth(0)
def resizeEvent(self, event):
super().resizeEvent(event)
cr = self.contentsRect()
self.lineNumberArea.setGeometry(
QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height())
)

View File

@@ -30,13 +30,16 @@ These are common functions and classes for creating custom post processors.
from Path.Base.MachineState import MachineState
from Path.Main.Gui.Editor import CodeEditor
from PySide import QtCore, QtGui
import FreeCAD
import Part
import Path
import os
import re
debug = False
if debug:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
@@ -215,14 +218,16 @@ class GCodeEditorDialog(QtGui.QDialog):
layout = QtGui.QVBoxLayout(self)
# nice text editor widget for editing the gcode
self.editor = QtGui.QTextEdit()
# self.editor = QtGui.QTextEdit() # without lines enumeration
self.editor = CodeEditor() # with lines enumeration
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor")
font = QtGui.QFont()
font.setFamily("Courier")
font.setFamily(p.GetString("Font", "Courier"))
font.setFixedPitch(True)
font.setPointSize(10)
font.setPointSize(p.GetInt("FontSize", 10))
self.editor.setFont(font)
self.editor.setText("G01 X55 Y4.5 F300.0")
self.editor.setPlainText("G01 X55 Y4.5 F300.0")
layout.addWidget(self.editor)
# OK and Cancel buttons

View File

@@ -338,12 +338,12 @@ def export_common(values: Values, objectslist, filename: str) -> str:
dia = PostUtils.GCodeEditorDialog()
# the editor expects lines to end in "\n", and returns lines ending in "\n"
if values["END_OF_LINE_CHARACTERS"] == "\n":
dia.editor.setText(final)
dia.editor.setPlainText(final)
if dia.exec_():
final = dia.editor.toPlainText()
else:
final_for_editor = "\n".join(gcode)
dia.editor.setText(final_for_editor)
dia.editor.setPlainText(final_for_editor)
if dia.exec_():
final_for_editor = dia.editor.toPlainText()
# convert all "\n" to the appropriate end-of-line characters

View File

@@ -259,7 +259,7 @@ def export(objectslist, filename, argstring):
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -225,7 +225,7 @@ def export(objectslist, filename, argstring):
if SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -292,7 +292,7 @@ def export(objectslist, filename, argstring):
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -263,7 +263,7 @@ def export(objectslist, filename, argstring):
print("show editor: {}".format(SHOW_EDITOR))
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -312,7 +312,7 @@ def export(objectslist, filename, argstring):
# show the gCode result dialog
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -190,7 +190,7 @@ def export(objectslist, filename, argstring):
if SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -255,7 +255,7 @@ def export(objectslist, filename, argstring):
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
if dia.exec_():
final = dia.editor.toPlainText()
else:

View File

@@ -276,7 +276,7 @@ def export(objectslist, filename, argstring):
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -370,7 +370,7 @@ def export(objectslist, filename, argstring):
# show the gCode result dialog
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -228,7 +228,7 @@ def export(objectslist, filename, argstring):
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -252,7 +252,7 @@ def export(objectslist, filename, argstring):
print("Skipping editor since output is greater than 100kb")
else:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -252,7 +252,7 @@ def export(objectslist, filename, argstring):
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -440,7 +440,7 @@ def export(objectslist, filename, argstring):
# Show the gcode result dialog:
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -124,7 +124,7 @@ def export(objectslist, filename, argstring):
# Open editor window
if FreeCAD.GuiUp:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
gcode = dia.editor.toPlainText()

View File

@@ -171,7 +171,7 @@ def export(objectslist, filename, argstring):
if SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -433,7 +433,7 @@ def export(objectslist, filename, argstring):
# Show the gcode result dialog:
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -815,12 +815,12 @@ class Snapmaker(Path.Post.Processor.PostProcessor):
dia = PostUtils.GCodeEditorDialog()
# the editor expects lines to end in "\n", and returns lines ending in "\n"
if self.values["END_OF_LINE_CHARACTERS"] == "\n":
dia.editor.setText(final)
dia.editor.setPlainText(final)
if dia.exec_():
final = dia.editor.toPlainText()
else:
final_for_editor = "\n".join(gcode)
dia.editor.setText(final_for_editor)
dia.editor.setPlainText(final_for_editor)
if dia.exec_():
final_for_editor = dia.editor.toPlainText()
# convert all "\n" to the appropriate end-of-line characters

View File

@@ -507,7 +507,7 @@ def export(objectslist, filename, argstring):
# Show the results
if SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()

View File

@@ -356,7 +356,7 @@ def export(objectslist, filename, argstring):
print("Skipping editor since output is greater than 100kb")
else:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
dia.editor.setPlainText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()