diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 3b91a598..f21a830d 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -92,8 +92,8 @@ class App(QtCore.QObject): log.addHandler(handler) # Version - version = 8.909 - version_date = "2019/02/16" + version = 8.910 + version_date = "2019/02/23" beta = True # current date now @@ -1129,7 +1129,7 @@ class App(QtCore.QObject): self.ui.menuoptions_transform_flipx.triggered.connect(self.on_flipx) self.ui.menuoptions_transform_flipy.triggered.connect(self.on_flipy) - + self.ui.menuoptions_view_source.triggered.connect(self.on_view_source) self.ui.menuviewdisableall.triggered.connect(self.disable_all_plots) self.ui.menuviewdisableother.triggered.connect(self.disable_other_plots) @@ -1156,6 +1156,8 @@ class App(QtCore.QObject): self.ui.menuprojectenable.triggered.connect(lambda: self.enable_plots(self.collection.get_selected())) self.ui.menuprojectdisable.triggered.connect(lambda: self.disable_plots(self.collection.get_selected())) self.ui.menuprojectgeneratecnc.triggered.connect(lambda: self.generate_cnc_job(self.collection.get_selected())) + self.ui.menuprojectviewsource.triggered.connect(self.on_view_source) + self.ui.menuprojectcopy.triggered.connect(self.on_copy_object) self.ui.menuprojectedit.triggered.connect(self.object2editor) @@ -3934,7 +3936,7 @@ class App(QtCore.QObject): obj.mirror('X', [px, py]) obj.plot() self.object_changed.emit(obj) - + self.inform.emit("[success] Flip on Y axis done.") except Exception as e: self.inform.emit("[ERROR_NOTCL] Due of %s, Flip action was not executed." % str(e)) return @@ -3974,7 +3976,7 @@ class App(QtCore.QObject): obj.mirror('Y', [px, py]) obj.plot() self.object_changed.emit(obj) - + self.inform.emit("[success] Flip on X axis done.") except Exception as e: self.inform.emit("[ERROR_NOTCL] Due of %s, Flip action was not executed." % str(e)) return @@ -4021,6 +4023,7 @@ class App(QtCore.QObject): sel_obj.rotate(-num, point=(px, py)) sel_obj.plot() self.object_changed.emit(sel_obj) + self.inform.emit("[success] Rotation done.") except Exception as e: self.inform.emit("[ERROR_NOTCL] Due of %s, rotation movement was not executed." % str(e)) return @@ -4053,6 +4056,7 @@ class App(QtCore.QObject): obj.skew(num, 0, point=(xminimal, yminimal)) obj.plot() self.object_changed.emit(obj) + self.inform.emit("[success] Skew on X axis done.") def on_skewy(self): self.report_usage("on_skewy()") @@ -4082,6 +4086,7 @@ class App(QtCore.QObject): obj.skew(0, num, point=(xminimal, yminimal)) obj.plot() self.object_changed.emit(obj) + self.inform.emit("[success] Skew on Y axis done.") def delete_first_selected(self): # Keep this for later @@ -4729,9 +4734,44 @@ class App(QtCore.QObject): elif type(obj) == FlatCAMCNCjob: obj.on_exportgcode_button_click() + def on_view_source(self): + + try: + obj = self.collection.get_active() + except: + self.inform.emit("[WARNING_NOTCL] Select an Gerber or Excellon file to view it's source.") + + # add the tab if it was closed + self.ui.plot_tab_area.addTab(self.ui.cncjob_tab, "Code Editor") + # first clear previous text in text editor (if any) + self.ui.code_editor.clear() + + # Switch plot_area to CNCJob tab + self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab) + + # then append the text from GCode to the text editor + file = StringIO(obj.source_file) + try: + for line in file: + proc_line = str(line).strip('\n') + self.ui.code_editor.append(proc_line) + except Exception as e: + log.debug('App.on_view_source() -->%s' % str(e)) + self.inform.emit('[ERROR]App.on_view_source() -->%s' % str(e)) + return + + self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start) + + self.handleTextChanged() + self.ui.show() + + # if type(obj) == FlatCAMGerber: + # self.on_file_exportdxf() + # elif type(obj) == FlatCAMExcellon: + # self.on_file_exportexcellon() + def obj_move(self): self.report_usage("obj_move()") - self.move_tool.run() def on_fileopengerber(self): diff --git a/FlatCAMGUI.py b/FlatCAMGUI.py index 770b16ff..1a2c7f42 100644 --- a/FlatCAMGUI.py +++ b/FlatCAMGUI.py @@ -292,6 +292,11 @@ class FlatCAMGUI(QtWidgets.QMainWindow): # Separator self.menuoptions.addSeparator() + self.menuoptions_view_source = self.menuoptions.addAction(QtGui.QIcon('share/source32.png'), + "View source\tALT+S") + # Separator + self.menuoptions.addSeparator() + ### View ### self.menuview = self.menu.addMenu('&View') self.menuviewenable = self.menuview.addAction(QtGui.QIcon('share/replot16.png'), 'Enable all plots\tALT+1') @@ -419,7 +424,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.menuprojectdisable = self.menuproject.addAction(QtGui.QIcon('share/clear_plot32.png'), 'Disable Plot') self.menuproject.addSeparator() self.menuprojectgeneratecnc = self.menuproject.addAction(QtGui.QIcon('share/cnc32.png'), 'Generate CNC') - self.menuproject.addSeparator() + self.menuprojectviewsource = self.menuproject.addAction(QtGui.QIcon('share/source32.png'), 'View Source') self.menuprojectedit = self.menuproject.addAction(QtGui.QIcon('share/edit_ok32.png'), 'Edit') self.menuprojectcopy = self.menuproject.addAction(QtGui.QIcon('share/copy32.png'), 'Copy') @@ -999,6 +1004,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow): ALT+R  Transformations Tool + + ALT+S +  View File Source + ALT+U  Cutout PCB Tool @@ -1294,8 +1303,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.code_editor.setStyleSheet(stylesheet) self.buttonPreview = QtWidgets.QPushButton('Print Preview') - self.buttonPrint = QtWidgets.QPushButton('Print CNC Code') - self.buttonFind = QtWidgets.QPushButton('Find in CNC Code') + self.buttonPrint = QtWidgets.QPushButton('Print Code') + self.buttonFind = QtWidgets.QPushButton('Find in Code') self.buttonFind.setFixedWidth(100) self.buttonPreview.setFixedWidth(100) self.entryFind = FCEntry() @@ -1309,8 +1318,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow): "When checked it will replace all instances in the 'Find' box\n" "with the text in the 'Replace' box.." ) - self.buttonOpen = QtWidgets.QPushButton('Open CNC Code') - self.buttonSave = QtWidgets.QPushButton('Save CNC Code') + self.buttonOpen = QtWidgets.QPushButton('Open Code') + self.buttonSave = QtWidgets.QPushButton('Save Code') self.cncjob_tab_layout.addWidget(self.code_editor, 0, 0, 1, 5) @@ -1711,6 +1720,11 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.app.transform_tool.run() return + # Transformation Tool + if key == QtCore.Qt.Key_S: + self.app.on_view_source() + return + # Cutout Tool if key == QtCore.Qt.Key_U: self.app.cutout_tool.run() diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 34ff30db..bd17c810 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -422,6 +422,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber): self.apertures_row = 0 + # store the source file here + self.source_file = "" + # assert isinstance(self.ui, GerberObjectUI) # self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click) # self.ui.solid_cb.stateChanged.connect(self.on_solid_cb_click) @@ -1092,6 +1095,9 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): # variable to store the distance travelled self.travel_distance = 0.0 + # store the source file here + self.source_file = "" + self.multigeo = False @staticmethod @@ -4809,7 +4815,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): def on_modifygcode_button_click(self, *args): # add the tab if it was closed - self.app.ui.plot_tab_area.addTab(self.app.ui.cncjob_tab, "CNC Code Editor") + self.app.ui.plot_tab_area.addTab(self.app.ui.cncjob_tab, "Code Editor") # delete the absolute and relative position and messages in the infobar self.app.ui.position_label.setText("") @@ -4821,7 +4827,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): preamble = str(self.ui.prepend_text.get_value()) postamble = str(self.ui.append_text.get_value()) self.app.gcode_edited = self.export_gcode(preamble=preamble, postamble=postamble, to_file=True) - # print(self.app.gcode_edited) + # first clear previous text in text editor (if any) self.app.ui.code_editor.clear() diff --git a/ObjectCollection.py b/ObjectCollection.py index dc60edec..59d96b14 100644 --- a/ObjectCollection.py +++ b/ObjectCollection.py @@ -504,6 +504,8 @@ class ObjectCollection(QtCore.QAbstractItemModel): sel = len(self.view.selectedIndexes()) > 0 self.app.ui.menuprojectenable.setEnabled(sel) self.app.ui.menuprojectdisable.setEnabled(sel) + self.app.ui.menuprojectviewsource.setEnabled(sel) + self.app.ui.menuprojectcopy.setEnabled(sel) self.app.ui.menuprojectedit.setEnabled(sel) self.app.ui.menuprojectdelete.setEnabled(sel) @@ -514,6 +516,7 @@ class ObjectCollection(QtCore.QAbstractItemModel): self.app.ui.menuprojectgeneratecnc.setVisible(True) self.app.ui.menuprojectedit.setVisible(True) self.app.ui.menuprojectsave.setVisible(True) + self.app.ui.menuprojectviewsource.setVisible(True) for obj in self.get_selected(): if type(obj) != FlatCAMGeometry: @@ -522,6 +525,8 @@ class ObjectCollection(QtCore.QAbstractItemModel): self.app.ui.menuprojectedit.setVisible(False) if type(obj) != FlatCAMGeometry and type(obj) != FlatCAMExcellon and type(obj) != FlatCAMCNCjob: self.app.ui.menuprojectsave.setVisible(False) + if type(obj) != FlatCAMGerber and type(obj) != FlatCAMExcellon: + self.app.ui.menuprojectviewsource.setVisible(False) else: self.app.ui.menuprojectgeneratecnc.setVisible(False) diff --git a/ObjectUI.py b/ObjectUI.py index 1dc9074e..a97ec8e4 100644 --- a/ObjectUI.py +++ b/ObjectUI.py @@ -1338,9 +1338,9 @@ class CNCObjectUI(ObjectUI): self.custom_box.addLayout(h_lay) # Edit GCode Button - self.modify_gcode_button = QtWidgets.QPushButton('Edit CNC Code') + self.modify_gcode_button = QtWidgets.QPushButton('View CNC Code') self.modify_gcode_button.setToolTip( - "Opens TAB to modify/print G-Code\n" + "Opens TAB to view/modify/print G-Code\n" "file." ) diff --git a/README.md b/README.md index 51f70fbd..e88f9235 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing. ================================================= +17.02.2019 + +- changed some status bar messages +- New feature: added the capability to view the source code of the Gerber/Excellon file that was loaded into the app. The file is also stored as an object attribute for later use. THe view option is in the project context menu and in Menu -> Options -> View Source + 16.02.2019 - added the 'Save' menu entry to the Project context menu, for CNCJob: it will export the GCode. diff --git a/camlib.py b/camlib.py index bbe3de02..ddc76a05 100644 --- a/camlib.py +++ b/camlib.py @@ -2185,6 +2185,8 @@ class Gerber (Geometry): for gline in glines: line_num += 1 + self.source_file += gline + '\n' + ### Cleanup gline = gline.strip(' \r\n') # log.debug("Line=%3s %s" % (line_num, gline)) @@ -3469,6 +3471,8 @@ class Excellon(Geometry): line_num += 1 # log.debug("%3d %s" % (line_num, str(eline))) + self.source_file += eline + # Cleanup lines eline = eline.strip(' \r\n') @@ -3819,7 +3823,7 @@ class Excellon(Geometry): self.drills.append({'point': Point((coordx, coordy)), 'tool': current_tool}) repeat -= 1 repeating_x = repeating_y = 0 - log.debug("{:15} {:8} {:8}".format(eline, x, y)) + # log.debug("{:15} {:8} {:8}".format(eline, x, y)) continue ## Coordinates with period: Use literally. ## @@ -3901,7 +3905,7 @@ class Excellon(Geometry): self.drills.append({'point': Point((coordx, coordy)), 'tool': current_tool}) repeat -= 1 repeating_x = repeating_y = 0 - log.debug("{:15} {:8} {:8}".format(eline, x, y)) + # log.debug("{:15} {:8} {:8}".format(eline, x, y)) continue #### Header #### @@ -4004,7 +4008,6 @@ class Excellon(Geometry): # is finished since the tools definitions are spread in the Excellon body. We use as units the value # from self.defaults['excellon_units'] log.info("Zeros: %s, Units %s." % (self.zeros, self.units)) - except Exception as e: log.error("Excellon PARSING FAILED. Line %d: %s" % (line_num, eline)) msg = "[ERROR_NOTCL] An internal error has ocurred. See shell.\n" diff --git a/flatcamTools/ToolTransform.py b/flatcamTools/ToolTransform.py index 77c6561e..0819e329 100644 --- a/flatcamTools/ToolTransform.py +++ b/flatcamTools/ToolTransform.py @@ -595,7 +595,7 @@ class ToolTransform(FlatCAMTool): # add information to the object that it was changed and how much sel_obj.options['rotate'] = num - self.app.inform.emit('Object(s) were rotated ...') + self.app.inform.emit('[success]Rotate done ...') self.app.progress.emit(100) except Exception as e: @@ -656,7 +656,7 @@ class ToolTransform(FlatCAMTool): else: obj.options['mirror_y'] = True obj.plot() - self.app.inform.emit('Flipped on the Y axis ...') + self.app.inform.emit('[success]Flip on the Y axis done ...') elif axis is 'Y': obj.mirror('Y', (px, py)) # add information to the object that it was changed and how much @@ -666,9 +666,8 @@ class ToolTransform(FlatCAMTool): else: obj.options['mirror_x'] = True obj.plot() - self.app.inform.emit('Flipped on the X axis ...') + self.app.inform.emit('[success]Flip on the X axis done ...') self.app.object_changed.emit(obj) - self.app.progress.emit(100) except Exception as e: @@ -715,7 +714,7 @@ class ToolTransform(FlatCAMTool): obj.options['skew_y'] = num obj.plot() self.app.object_changed.emit(obj) - self.app.inform.emit('Object(s) were skewed on %s axis ...' % str(axis)) + self.app.inform.emit('[success]Skew on the %s axis done ...' % str(axis)) self.app.progress.emit(100) except Exception as e: @@ -771,7 +770,7 @@ class ToolTransform(FlatCAMTool): obj.options['scale_y'] = yfactor obj.plot() self.app.object_changed.emit(obj) - self.app.inform.emit('Object(s) were scaled on %s axis ...' % str(axis)) + self.app.inform.emit('[success]Scale on the %s axis done ...' % str(axis)) self.app.progress.emit(100) except Exception as e: self.app.inform.emit("[ERROR_NOTCL] Due of %s, Scale action was not executed." % str(e)) @@ -816,7 +815,7 @@ class ToolTransform(FlatCAMTool): obj.options['offset_y'] = num obj.plot() self.app.object_changed.emit(obj) - self.app.inform.emit('Object(s) were offseted on %s axis ...' % str(axis)) + self.app.inform.emit('[success]Offset on the %s axis done ...' % str(axis)) self.app.progress.emit(100) except Exception as e: diff --git a/make_win.py b/make_win.py index fac62161..812130b2 100644 --- a/make_win.py +++ b/make_win.py @@ -73,7 +73,7 @@ else: excludes=['scipy', 'pytz'], # packages=['OpenGL','numpy','vispy','ortools','google'] # packages=['numpy', 'rasterio'] # works for Python 3.7 - packages = ['opengl', 'numpy', 'google', 'rasterio'] # works for Python 3.6.5 and Python 3.7.1 + packages = ['opengl', 'numpy', 'rasterio'] # works for Python 3.6.5 and Python 3.7.1 ) diff --git a/share/source32.png b/share/source32.png new file mode 100644 index 00000000..9f6db60a Binary files /dev/null and b/share/source32.png differ