appGCodeEditor.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. # ##########################################################
  2. # FlatCAM: 2D Post-processing for Manufacturing #
  3. # File Author: Marius Adrian Stanciu (c) #
  4. # Date: 07/22/2020 #
  5. # MIT Licence #
  6. # ##########################################################
  7. from appEditors.AppTextEditor import AppTextEditor
  8. from appObjects.FlatCAMCNCJob import CNCJobObject
  9. from appGUI.GUIElements import FCTextArea, FCEntry, FCButton, FCTable
  10. from PyQt5 import QtWidgets, QtCore, QtGui
  11. # from io import StringIO
  12. import logging
  13. import gettext
  14. import appTranslation as fcTranslate
  15. import builtins
  16. fcTranslate.apply_language('strings')
  17. if '_' not in builtins.__dict__:
  18. _ = gettext.gettext
  19. log = logging.getLogger('base')
  20. class AppGCodeEditor(QtCore.QObject):
  21. def __init__(self, app, parent=None):
  22. super().__init__(parent=parent)
  23. self.app = app
  24. self.decimals = self.app.decimals
  25. self.plain_text = ''
  26. self.callback = lambda x: None
  27. self.ui = AppGCodeEditorUI(app=self.app)
  28. self.edited_obj_name = ""
  29. self.gcode_obj = None
  30. self.code_edited = ''
  31. # store the status of the editor so the Delete at object level will not work until the edit is finished
  32. self.editor_active = False
  33. log.debug("Initialization of the GCode Editor is finished ...")
  34. def set_ui(self):
  35. """
  36. :return:
  37. :rtype:
  38. """
  39. self.decimals = self.app.decimals
  40. # #############################################################################################################
  41. # ############# ADD a new TAB in the PLot Tab Area
  42. # #############################################################################################################
  43. self.ui.gcode_editor_tab = AppTextEditor(app=self.app, plain_text=True)
  44. # add the tab if it was closed
  45. self.app.ui.plot_tab_area.addTab(self.ui.gcode_editor_tab, '%s' % _("Code Editor"))
  46. self.ui.gcode_editor_tab.setObjectName('code_editor_tab')
  47. # delete the absolute and relative position and messages in the infobar
  48. self.app.ui.position_label.setText("")
  49. self.app.ui.rel_position_label.setText("")
  50. self.ui.gcode_editor_tab.code_editor.completer_enable = False
  51. self.ui.gcode_editor_tab.buttonRun.hide()
  52. # Switch plot_area to CNCJob tab
  53. self.app.ui.plot_tab_area.setCurrentWidget(self.ui.gcode_editor_tab)
  54. self.ui.gcode_editor_tab.t_frame.hide()
  55. self.ui.gcode_editor_tab.t_frame.show()
  56. self.app.proc_container.view.set_idle()
  57. # #############################################################################################################
  58. # #############################################################################################################
  59. self.ui.append_text.set_value(self.app.defaults["cncjob_append"])
  60. self.ui.prepend_text.set_value(self.app.defaults["cncjob_prepend"])
  61. # Remove anything else in the GUI Selected Tab
  62. self.app.ui.selected_scroll_area.takeWidget()
  63. # Put ourselves in the GUI Selected Tab
  64. self.app.ui.selected_scroll_area.setWidget(self.ui.edit_widget)
  65. # Switch notebook to Selected page
  66. self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
  67. # make a new name for the new Excellon object (the one with edited content)
  68. self.edited_obj_name = self.gcode_obj.options['name']
  69. self.ui.name_entry.set_value(self.edited_obj_name)
  70. # #################################################################################
  71. # ################### SIGNALS #####################################################
  72. # #################################################################################
  73. self.ui.name_entry.returnPressed.connect(self.on_name_activate)
  74. self.ui.update_gcode_button.clicked.connect(self.insert_gcode)
  75. self.ui.exit_editor_button.clicked.connect(lambda: self.app.editor2object())
  76. def build_ui(self):
  77. """
  78. :return:
  79. :rtype:
  80. """
  81. self.ui_disconnect()
  82. # if the FlatCAM object is Excellon don't build the CNC Tools Table but hide it
  83. self.ui.cnc_tools_table.hide()
  84. if self.gcode_obj.cnc_tools:
  85. self.ui.cnc_tools_table.show()
  86. self.build_cnc_tools_table()
  87. self.ui.exc_cnc_tools_table.hide()
  88. if self.gcode_obj.exc_cnc_tools:
  89. self.ui.exc_cnc_tools_table.show()
  90. self.build_excellon_cnc_tools()
  91. self.ui_connect()
  92. def build_cnc_tools_table(self):
  93. tool_idx = 0
  94. row_no = 0
  95. n = len(self.gcode_obj.cnc_tools) + 2
  96. self.ui.cnc_tools_table.setRowCount(n)
  97. # add the Start Gcode selection
  98. start_item = QtWidgets.QTableWidgetItem('%s' % _("Header GCode"))
  99. start_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  100. self.ui.cnc_tools_table.setItem(row_no, 1, start_item)
  101. for dia_key, dia_value in self.gcode_obj.cnc_tools.items():
  102. tool_idx += 1
  103. row_no += 1
  104. t_id = QtWidgets.QTableWidgetItem('%d' % int(tool_idx))
  105. # id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  106. self.ui.cnc_tools_table.setItem(row_no, 0, t_id) # Tool name/id
  107. dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(dia_value['tooldia'])))
  108. offset_txt = list(str(dia_value['offset']))
  109. offset_txt[0] = offset_txt[0].upper()
  110. offset_item = QtWidgets.QTableWidgetItem(''.join(offset_txt))
  111. type_item = QtWidgets.QTableWidgetItem(str(dia_value['type']))
  112. tool_type_item = QtWidgets.QTableWidgetItem(str(dia_value['tool_type']))
  113. t_id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  114. dia_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  115. offset_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  116. type_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  117. tool_type_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  118. self.ui.cnc_tools_table.setItem(row_no, 1, dia_item) # Diameter
  119. self.ui.cnc_tools_table.setItem(row_no, 2, offset_item) # Offset
  120. self.ui.cnc_tools_table.setItem(row_no, 3, type_item) # Toolpath Type
  121. self.ui.cnc_tools_table.setItem(row_no, 4, tool_type_item) # Tool Type
  122. tool_uid_item = QtWidgets.QTableWidgetItem(str(dia_key))
  123. # ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY # ##
  124. self.ui.cnc_tools_table.setItem(row_no, 5, tool_uid_item) # Tool unique ID)
  125. # add the All Gcode selection
  126. end_item = QtWidgets.QTableWidgetItem('%s' % _("All GCode"))
  127. end_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  128. self.ui.cnc_tools_table.setItem(row_no + 1, 1, end_item)
  129. self.ui.cnc_tools_table.resizeColumnsToContents()
  130. self.ui.cnc_tools_table.resizeRowsToContents()
  131. vertical_header = self.ui.cnc_tools_table.verticalHeader()
  132. # vertical_header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
  133. vertical_header.hide()
  134. self.ui.cnc_tools_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
  135. horizontal_header = self.ui.cnc_tools_table.horizontalHeader()
  136. horizontal_header.setMinimumSectionSize(10)
  137. horizontal_header.setDefaultSectionSize(70)
  138. horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
  139. horizontal_header.resizeSection(0, 20)
  140. horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
  141. horizontal_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
  142. horizontal_header.setSectionResizeMode(4, QtWidgets.QHeaderView.Fixed)
  143. horizontal_header.resizeSection(4, 40)
  144. # horizontal_header.setStretchLastSection(True)
  145. self.ui.cnc_tools_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
  146. self.ui.cnc_tools_table.setColumnWidth(0, 20)
  147. self.ui.cnc_tools_table.setColumnWidth(4, 40)
  148. self.ui.cnc_tools_table.setColumnWidth(6, 17)
  149. # self.ui.geo_tools_table.setSortingEnabled(True)
  150. self.ui.cnc_tools_table.setMinimumHeight(self.ui.cnc_tools_table.getHeight())
  151. self.ui.cnc_tools_table.setMaximumHeight(self.ui.cnc_tools_table.getHeight())
  152. def build_excellon_cnc_tools(self):
  153. """
  154. :return:
  155. :rtype:
  156. """
  157. tool_idx = 0
  158. row_no = 0
  159. n = len(self.gcode_obj.exc_cnc_tools) + 2
  160. self.ui.exc_cnc_tools_table.setRowCount(n)
  161. # add the Start Gcode selection
  162. start_item = QtWidgets.QTableWidgetItem('%s' % _("Header GCode"))
  163. start_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  164. self.ui.exc_cnc_tools_table.setItem(row_no, 1, start_item)
  165. for tooldia_key, dia_value in self.gcode_obj.exc_cnc_tools.items():
  166. tool_idx += 1
  167. row_no += 1
  168. t_id = QtWidgets.QTableWidgetItem('%d' % int(tool_idx))
  169. dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(tooldia_key)))
  170. nr_drills_item = QtWidgets.QTableWidgetItem('%d' % int(dia_value['nr_drills']))
  171. nr_slots_item = QtWidgets.QTableWidgetItem('%d' % int(dia_value['nr_slots']))
  172. cutz_item = QtWidgets.QTableWidgetItem('%.*f' % (
  173. self.decimals, float(dia_value['offset']) + float(dia_value['data']['tools_drill_cutz'])))
  174. t_id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  175. dia_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  176. nr_drills_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  177. nr_slots_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  178. cutz_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  179. self.ui.exc_cnc_tools_table.setItem(row_no, 0, t_id) # Tool name/id
  180. self.ui.exc_cnc_tools_table.setItem(row_no, 1, dia_item) # Diameter
  181. self.ui.exc_cnc_tools_table.setItem(row_no, 2, nr_drills_item) # Nr of drills
  182. self.ui.exc_cnc_tools_table.setItem(row_no, 3, nr_slots_item) # Nr of slots
  183. tool_uid_item = QtWidgets.QTableWidgetItem(str(dia_value['tool']))
  184. # ## REMEMBER: THIS COLUMN IS HIDDEN IN OBJECTUI.PY # ##
  185. self.ui.exc_cnc_tools_table.setItem(row_no, 4, tool_uid_item) # Tool unique ID)
  186. self.ui.exc_cnc_tools_table.setItem(row_no, 5, cutz_item)
  187. # add the All Gcode selection
  188. end_item = QtWidgets.QTableWidgetItem('%s' % _("All GCode"))
  189. end_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  190. self.ui.exc_cnc_tools_table.setItem(row_no + 1, 1, end_item)
  191. self.ui.exc_cnc_tools_table.resizeColumnsToContents()
  192. self.ui.exc_cnc_tools_table.resizeRowsToContents()
  193. vertical_header = self.ui.exc_cnc_tools_table.verticalHeader()
  194. vertical_header.hide()
  195. self.ui.exc_cnc_tools_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
  196. horizontal_header = self.ui.exc_cnc_tools_table.horizontalHeader()
  197. horizontal_header.setMinimumSectionSize(10)
  198. horizontal_header.setDefaultSectionSize(70)
  199. horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
  200. horizontal_header.resizeSection(0, 20)
  201. horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
  202. horizontal_header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
  203. horizontal_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
  204. horizontal_header.setSectionResizeMode(5, QtWidgets.QHeaderView.ResizeToContents)
  205. # horizontal_header.setStretchLastSection(True)
  206. self.ui.exc_cnc_tools_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
  207. self.ui.exc_cnc_tools_table.setColumnWidth(0, 20)
  208. self.ui.exc_cnc_tools_table.setColumnWidth(6, 17)
  209. self.ui.exc_cnc_tools_table.setMinimumHeight(self.ui.exc_cnc_tools_table.getHeight())
  210. self.ui.exc_cnc_tools_table.setMaximumHeight(self.ui.exc_cnc_tools_table.getHeight())
  211. def ui_connect(self):
  212. """
  213. :return:
  214. :rtype:
  215. """
  216. # rows selected
  217. if self.gcode_obj.cnc_tools:
  218. self.ui.cnc_tools_table.clicked.connect(self.on_row_selection_change)
  219. self.ui.cnc_tools_table.horizontalHeader().sectionClicked.connect(self.on_toggle_all_rows)
  220. if self.gcode_obj.exc_cnc_tools:
  221. self.ui.exc_cnc_tools_table.clicked.connect(self.on_row_selection_change)
  222. self.ui.exc_cnc_tools_table.horizontalHeader().sectionClicked.connect(self.on_toggle_all_rows)
  223. def ui_disconnect(self):
  224. """
  225. :return:
  226. :rtype:
  227. """
  228. # rows selected
  229. if self.gcode_obj.cnc_tools:
  230. try:
  231. self.ui.cnc_tools_table.clicked.disconnect(self.on_row_selection_change)
  232. except (TypeError, AttributeError):
  233. pass
  234. try:
  235. self.ui.cnc_tools_table.horizontalHeader().sectionClicked.disconnect(self.on_toggle_all_rows)
  236. except (TypeError, AttributeError):
  237. pass
  238. if self.gcode_obj.exc_cnc_tools:
  239. try:
  240. self.ui.exc_cnc_tools_table.clicked.disconnect(self.on_row_selection_change)
  241. except (TypeError, AttributeError):
  242. pass
  243. try:
  244. self.ui.exc_cnc_tools_table.horizontalHeader().sectionClicked.disconnect(self.on_toggle_all_rows)
  245. except (TypeError, AttributeError):
  246. pass
  247. def on_row_selection_change(self):
  248. """
  249. :return:
  250. :rtype:
  251. """
  252. if self.gcode_obj.cnc_tools:
  253. sel_model = self.ui.cnc_tools_table.selectionModel()
  254. elif self.gcode_obj.exc_cnc_tools:
  255. sel_model = self.ui.exc_cnc_tools_table.selectionModel()
  256. else:
  257. return
  258. sel_indexes = sel_model.selectedIndexes()
  259. # it will iterate over all indexes which means all items in all columns too but I'm interested only on rows
  260. sel_rows = set()
  261. for idx in sel_indexes:
  262. sel_rows.add(idx.row())
  263. def on_toggle_all_rows(self):
  264. """
  265. :return:
  266. :rtype:
  267. """
  268. if self.gcode_obj.cnc_tools:
  269. sel_model = self.ui.cnc_tools_table.selectionModel()
  270. elif self.gcode_obj.exc_cnc_tools:
  271. sel_model = self.ui.exc_cnc_tools_table.selectionModel()
  272. else:
  273. return
  274. sel_indexes = sel_model.selectedIndexes()
  275. # it will iterate over all indexes which means all items in all columns too but I'm interested only on rows
  276. sel_rows = set()
  277. for idx in sel_indexes:
  278. sel_rows.add(idx.row())
  279. if self.gcode_obj.cnc_tools:
  280. if len(sel_rows) == self.ui.cnc_tools_table.rowCount():
  281. self.ui.cnc_tools_table.clearSelection()
  282. else:
  283. self.ui.cnc_tools_table.selectAll()
  284. elif self.gcode_obj.exc_cnc_tools:
  285. if len(sel_rows) == self.ui.exc_cnc_tools_table.rowCount():
  286. self.ui.exc_cnc_tools_table.clearSelection()
  287. else:
  288. self.ui.exc_cnc_tools_table.selectAll()
  289. else:
  290. return
  291. def handleTextChanged(self):
  292. """
  293. :return:
  294. :rtype:
  295. """
  296. # enable = not self.ui.code_editor.document().isEmpty()
  297. # self.ui.buttonPrint.setEnabled(enable)
  298. # self.ui.buttonPreview.setEnabled(enable)
  299. self.buttonSave.setStyleSheet("QPushButton {color: red;}")
  300. self.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as_red.png'))
  301. def insert_gcode(self):
  302. """
  303. :return:
  304. :rtype:
  305. """
  306. pass
  307. def edit_fcgcode(self, cnc_obj):
  308. """
  309. :param cnc_obj:
  310. :type cnc_obj:
  311. :return:
  312. :rtype:
  313. """
  314. assert isinstance(cnc_obj, CNCJobObject)
  315. self.gcode_obj = cnc_obj
  316. gcode_text = self.gcode_obj.source_file
  317. self.set_ui()
  318. self.build_ui()
  319. # then append the text from GCode to the text editor
  320. self.ui.gcode_editor_tab.load_text(gcode_text, move_to_start=True, clear_text=True)
  321. self.app.inform.emit('[success] %s...' % _('Loaded Machine Code into Code Editor'))
  322. def update_fcgcode(self, edited_obj):
  323. """
  324. :return:
  325. :rtype:
  326. """
  327. preamble = str(self.ui.prepend_text.get_value())
  328. postamble = str(self.ui.append_text.get_value())
  329. my_gcode = self.ui.gcode_editor_tab.code_editor.toPlainText()
  330. self.gcode_obj.source_file = my_gcode
  331. self.ui.gcode_editor_tab.buttonSave.setStyleSheet("")
  332. self.ui.gcode_editor_tab.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
  333. def on_open_gcode(self):
  334. """
  335. :return:
  336. :rtype:
  337. """
  338. _filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
  339. "All Files (*.*)"
  340. path, _f = QtWidgets.QFileDialog.getOpenFileName(
  341. caption=_('Open file'), directory=self.app.get_last_folder(), filter=_filter_)
  342. if path:
  343. file = QtCore.QFile(path)
  344. if file.open(QtCore.QIODevice.ReadOnly):
  345. stream = QtCore.QTextStream(file)
  346. self.code_edited = stream.readAll()
  347. self.ui.gcode_editor_tab.load_text(self.code_edited, move_to_start=True, clear_text=True)
  348. file.close()
  349. def on_name_activate(self):
  350. self.edited_obj_name = self.ui.name_entry.get_value()
  351. class AppGCodeEditorUI:
  352. def __init__(self, app):
  353. self.app = app
  354. # Number of decimals used by tools in this class
  355. self.decimals = self.app.decimals
  356. # ## Current application units in Upper Case
  357. self.units = self.app.defaults['units'].upper()
  358. # self.setSizePolicy(
  359. # QtWidgets.QSizePolicy.MinimumExpanding,
  360. # QtWidgets.QSizePolicy.MinimumExpanding
  361. # )
  362. self.gcode_editor_tab = None
  363. self.edit_widget = QtWidgets.QWidget()
  364. # ## Box for custom widgets
  365. # This gets populated in offspring implementations.
  366. layout = QtWidgets.QVBoxLayout()
  367. self.edit_widget.setLayout(layout)
  368. # add a frame and inside add a vertical box layout. Inside this vbox layout I add all the Drills widgets
  369. # this way I can hide/show the frame
  370. self.edit_frame = QtWidgets.QFrame()
  371. self.edit_frame.setContentsMargins(0, 0, 0, 0)
  372. layout.addWidget(self.edit_frame)
  373. self.edit_box = QtWidgets.QVBoxLayout()
  374. self.edit_box.setContentsMargins(0, 0, 0, 0)
  375. self.edit_frame.setLayout(self.edit_box)
  376. # ## Page Title box (spacing between children)
  377. self.title_box = QtWidgets.QHBoxLayout()
  378. self.edit_box.addLayout(self.title_box)
  379. # ## Page Title icon
  380. pixmap = QtGui.QPixmap(self.app.resource_location + '/flatcam_icon32.png')
  381. self.icon = QtWidgets.QLabel()
  382. self.icon.setPixmap(pixmap)
  383. self.title_box.addWidget(self.icon, stretch=0)
  384. # ## Title label
  385. self.title_label = QtWidgets.QLabel("<font size=5><b>%s</b></font>" % _('GCode Editor'))
  386. self.title_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
  387. self.title_box.addWidget(self.title_label, stretch=1)
  388. # ## Object name
  389. self.name_box = QtWidgets.QHBoxLayout()
  390. self.edit_box.addLayout(self.name_box)
  391. name_label = QtWidgets.QLabel(_("Name:"))
  392. self.name_box.addWidget(name_label)
  393. self.name_entry = FCEntry()
  394. self.name_box.addWidget(self.name_entry)
  395. separator_line = QtWidgets.QFrame()
  396. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  397. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  398. self.edit_box.addWidget(separator_line)
  399. # CNC Tools Table when made out of Geometry
  400. self.cnc_tools_table = FCTable()
  401. self.cnc_tools_table.setSortingEnabled(False)
  402. self.cnc_tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
  403. self.edit_box.addWidget(self.cnc_tools_table)
  404. self.cnc_tools_table.setColumnCount(6)
  405. self.cnc_tools_table.setColumnWidth(0, 20)
  406. self.cnc_tools_table.setHorizontalHeaderLabels(['#', _('Dia'), _('Offset'), _('Type'), _('TT'), ''])
  407. self.cnc_tools_table.setColumnHidden(5, True)
  408. # CNC Tools Table when made out of Excellon
  409. self.exc_cnc_tools_table = FCTable()
  410. self.exc_cnc_tools_table.setSortingEnabled(False)
  411. self.exc_cnc_tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
  412. self.edit_box.addWidget(self.exc_cnc_tools_table)
  413. self.exc_cnc_tools_table.setColumnCount(6)
  414. self.exc_cnc_tools_table.setColumnWidth(0, 20)
  415. self.exc_cnc_tools_table.setHorizontalHeaderLabels(['#', _('Dia'), _('Drills'), _('Slots'), '', _("Cut Z")])
  416. self.exc_cnc_tools_table.setColumnHidden(4, True)
  417. separator_line = QtWidgets.QFrame()
  418. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  419. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  420. self.edit_box.addWidget(separator_line)
  421. # Prepend text to GCode
  422. prependlabel = QtWidgets.QLabel('%s:' % _('Prepend to CNC Code'))
  423. prependlabel.setToolTip(
  424. _("Type here any G-Code commands you would\n"
  425. "like to add at the beginning of the G-Code file.")
  426. )
  427. self.edit_box.addWidget(prependlabel)
  428. self.prepend_text = FCTextArea()
  429. self.prepend_text.setPlaceholderText(
  430. _("Type here any G-Code commands you would\n"
  431. "like to add at the beginning of the G-Code file.")
  432. )
  433. self.edit_box.addWidget(self.prepend_text)
  434. # Append text to GCode
  435. appendlabel = QtWidgets.QLabel('%s:' % _('Append to CNC Code'))
  436. appendlabel.setToolTip(
  437. _("Type here any G-Code commands you would\n"
  438. "like to append to the generated file.\n"
  439. "I.e.: M2 (End of program)")
  440. )
  441. self.edit_box.addWidget(appendlabel)
  442. self.append_text = FCTextArea()
  443. self.append_text.setPlaceholderText(
  444. _("Type here any G-Code commands you would\n"
  445. "like to append to the generated file.\n"
  446. "I.e.: M2 (End of program)")
  447. )
  448. self.edit_box.addWidget(self.append_text)
  449. h_lay = QtWidgets.QHBoxLayout()
  450. h_lay.setAlignment(QtCore.Qt.AlignVCenter)
  451. self.edit_box.addLayout(h_lay)
  452. # GO Button
  453. self.update_gcode_button = FCButton(_('Update Code'))
  454. # self.update_gcode_button.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
  455. self.update_gcode_button.setToolTip(
  456. _("Update the Gcode in the Editor with the values\n"
  457. "in the 'Prepend' and 'Append' text boxes.")
  458. )
  459. h_lay.addWidget(self.update_gcode_button)
  460. layout.addStretch()
  461. # Editor
  462. self.exit_editor_button = FCButton(_('Exit Editor'))
  463. self.exit_editor_button.setIcon(QtGui.QIcon(self.app.resource_location + '/power16.png'))
  464. self.exit_editor_button.setToolTip(
  465. _("Exit from Editor.")
  466. )
  467. self.exit_editor_button.setStyleSheet("""
  468. QPushButton
  469. {
  470. font-weight: bold;
  471. }
  472. """)
  473. layout.addWidget(self.exit_editor_button)
  474. # ############################ FINSIHED GUI ##################################################################
  475. # #############################################################################################################
  476. def confirmation_message(self, accepted, minval, maxval):
  477. if accepted is False:
  478. self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' % (_("Edited value is out of range"),
  479. self.decimals,
  480. minval,
  481. self.decimals,
  482. maxval), False)
  483. else:
  484. self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
  485. def confirmation_message_int(self, accepted, minval, maxval):
  486. if accepted is False:
  487. self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%d, %d]' %
  488. (_("Edited value is out of range"), minval, maxval), False)
  489. else:
  490. self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)