commit
684ef77a7a
|
@ -3171,6 +3171,8 @@ class App(QtCore.QObject):
|
|||
# select the just opened object but deselect the previous ones
|
||||
self.collection.set_all_inactive()
|
||||
self.collection.set_active(obj.options["name"])
|
||||
else:
|
||||
self.collection.set_all_inactive()
|
||||
|
||||
# here it is done the object plotting
|
||||
def worker_task(t_obj):
|
||||
|
@ -4847,12 +4849,11 @@ class App(QtCore.QObject):
|
|||
# a geometry object before we update it.
|
||||
if self.geo_editor.editor_active is False and self.exc_editor.editor_active is False:
|
||||
if self.collection.get_active():
|
||||
self.log.debug("on_delete()")
|
||||
self.report_usage("on_delete")
|
||||
self.log.debug("App.on_delete()")
|
||||
|
||||
while (self.collection.get_active()):
|
||||
obj_active = self.collection.get_active()
|
||||
# if the deleted object is FlatCAMGerber then make sure to delete the possbile mark shapes
|
||||
# if the deleted object is FlatCAMGerber then make sure to delete the possible mark shapes
|
||||
if isinstance(obj_active, FlatCAMGerber):
|
||||
for el in obj_active.mark_shapes:
|
||||
obj_active.mark_shapes[el].clear(update=True)
|
||||
|
@ -4868,6 +4869,27 @@ class App(QtCore.QObject):
|
|||
else:
|
||||
self.inform.emit(_("Save the work in Editor and try again ..."))
|
||||
|
||||
def delete_first_selected(self):
|
||||
# Keep this for later
|
||||
try:
|
||||
sel_obj = self.collection.get_active()
|
||||
name = sel_obj.options["name"]
|
||||
except AttributeError:
|
||||
self.log.debug("Nothing selected for deletion")
|
||||
return
|
||||
|
||||
# Remove plot
|
||||
# self.plotcanvas.figure.delaxes(self.collection.get_active().axes)
|
||||
# self.plotcanvas.auto_adjust_axes()
|
||||
|
||||
# Clear form
|
||||
self.setup_component_editor()
|
||||
|
||||
# Remove from dictionary
|
||||
self.collection.delete_active()
|
||||
|
||||
self.inform.emit("Object deleted: %s" % name)
|
||||
|
||||
def on_set_origin(self):
|
||||
"""
|
||||
Set the origin to the left mouse click position
|
||||
|
@ -5485,26 +5507,6 @@ class App(QtCore.QObject):
|
|||
self.object_changed.emit(obj)
|
||||
self.inform.emit(_("[success] Skew on Y axis done."))
|
||||
|
||||
def delete_first_selected(self):
|
||||
# Keep this for later
|
||||
try:
|
||||
name = self.collection.get_active().options["name"]
|
||||
except AttributeError:
|
||||
self.log.debug("Nothing selected for deletion")
|
||||
return
|
||||
|
||||
# Remove plot
|
||||
# self.plotcanvas.figure.delaxes(self.collection.get_active().axes)
|
||||
# self.plotcanvas.auto_adjust_axes()
|
||||
|
||||
# Clear form
|
||||
self.setup_component_editor()
|
||||
|
||||
# Remove from dictionary
|
||||
self.collection.delete_active()
|
||||
|
||||
self.inform.emit("Object deleted: %s" % name)
|
||||
|
||||
def on_plots_updated(self):
|
||||
"""
|
||||
Callback used to report when the plots have changed.
|
||||
|
|
|
@ -183,7 +183,7 @@ class FlatCAMObj(QtCore.QObject):
|
|||
try:
|
||||
self.app.ui.selected_scroll_area.takeWidget()
|
||||
except Exception as e:
|
||||
self.app.log.debug("Nothing to remove")
|
||||
self.app.log.debug("FlatCAMObj.build_ui() --> Nothing to remove: %s" % str(e))
|
||||
self.app.ui.selected_scroll_area.setWidget(self.ui)
|
||||
|
||||
self.muted_ui = False
|
||||
|
@ -841,7 +841,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
:param outname: Base name of the output object
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if dia is None:
|
||||
dia = float(self.options["isotooldia"])
|
||||
if passes is None:
|
||||
|
@ -872,7 +871,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
try:
|
||||
geom = self.isolation_geometry(offset, iso_type=envelope_iso_type, follow=follow)
|
||||
except Exception as e:
|
||||
log.debug(str(e))
|
||||
log.debug('FlatCAMGerber.isolate().generate_envelope() --> %s' % str(e))
|
||||
return 'fail'
|
||||
|
||||
if invert:
|
||||
|
@ -880,16 +879,21 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
if type(geom) is MultiPolygon:
|
||||
pl = []
|
||||
for p in geom:
|
||||
pl.append(Polygon(p.exterior.coords[::-1], p.interiors))
|
||||
if p is not None:
|
||||
pl.append(Polygon(p.exterior.coords[::-1], p.interiors))
|
||||
geom = MultiPolygon(pl)
|
||||
elif type(geom) is Polygon:
|
||||
elif type(geom) is Polygon and geom is not None:
|
||||
geom = Polygon(geom.exterior.coords[::-1], geom.interiors)
|
||||
else:
|
||||
log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> Unexpected Geometry")
|
||||
except Exception as e:
|
||||
log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> %s" % str(e))
|
||||
return 'fail'
|
||||
return geom
|
||||
|
||||
if float(self.options["isotooldia"]) < 0:
|
||||
self.options["isotooldia"] = -self.options["isotooldia"]
|
||||
|
||||
if combine:
|
||||
if self.iso_type == 0:
|
||||
iso_name = self.options["name"] + "_ext_iso"
|
||||
|
@ -912,6 +916,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
geom = generate_envelope(iso_offset, 1, envelope_iso_type=self.iso_type, follow=follow)
|
||||
else:
|
||||
geom = generate_envelope(iso_offset, 0, envelope_iso_type=self.iso_type, follow=follow)
|
||||
if geom == 'fail':
|
||||
# app_obj.inform.emit(_("[ERROR_NOTCL] Isolation geometry could not be generated."))
|
||||
return 'fail'
|
||||
geo_obj.solid_geometry.append(geom)
|
||||
|
||||
# store here the default data for Geometry Data
|
||||
|
@ -1004,11 +1011,14 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
# if milling type is climb then the move is counter-clockwise around features
|
||||
if milling_type == 'cl':
|
||||
# geo_obj.solid_geometry = generate_envelope(offset, i == 0)
|
||||
geo_obj.solid_geometry = generate_envelope(offset, 1, envelope_iso_type=self.iso_type,
|
||||
follow=follow)
|
||||
geom = generate_envelope(offset, 1, envelope_iso_type=self.iso_type, follow=follow)
|
||||
else:
|
||||
geo_obj.solid_geometry = generate_envelope(offset, 0, envelope_iso_type=self.iso_type,
|
||||
follow=follow)
|
||||
geom = generate_envelope(offset, 0, envelope_iso_type=self.iso_type, follow=follow)
|
||||
if geom == 'fail':
|
||||
# app_obj.inform.emit(_("[ERROR_NOTCL] Isolation geometry could not be generated."))
|
||||
return 'fail'
|
||||
|
||||
geo_obj.solid_geometry = geom
|
||||
|
||||
# detect if solid_geometry is empty and this require list flattening which is "heavy"
|
||||
# or just looking in the lists (they are one level depth) and if any is not empty
|
||||
|
|
|
@ -159,6 +159,23 @@ def restart_program(app):
|
|||
Note: this function does not return. Any cleanup action (like
|
||||
saving data) must be done before calling this function.
|
||||
"""
|
||||
if app.should_we_save and app.collection.get_list():
|
||||
msgbox = QtWidgets.QMessageBox()
|
||||
msgbox.setText(_("There are files/objects modified in FlatCAM. "
|
||||
"\n"
|
||||
"Do you want to Save the project?"))
|
||||
msgbox.setWindowTitle(_("Save changes"))
|
||||
msgbox.setWindowIcon(QtGui.QIcon('share/save_as.png'))
|
||||
bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole)
|
||||
bt_no = msgbox.addButton(_('No'), QtWidgets.QMessageBox.NoRole)
|
||||
|
||||
msgbox.setDefaultButton(bt_yes)
|
||||
msgbox.exec_()
|
||||
response = msgbox.clickedButton()
|
||||
|
||||
if response == bt_yes:
|
||||
app.on_file_saveprojectas(thread=True, quit=True)
|
||||
|
||||
app.save_defaults()
|
||||
python = sys.executable
|
||||
os.execl(python, python, *sys.argv)
|
||||
|
|
15
README.md
15
README.md
|
@ -9,11 +9,26 @@ CAD program, and create G-Code for Isolation routing.
|
|||
|
||||
=================================================
|
||||
|
||||
6.08.2019
|
||||
|
||||
- fixed bug that crashed the app after creating a new geometry, if a new object is loaded and the new geometry is deleted and then trying to select the just loaded new object
|
||||
- made some GUI elements in Edit -> Preferences to have a minimum width as opposed to the previous fixed one
|
||||
- fixed issue in the isolation function, if the isolation can't be done there will be generated no Geometry object
|
||||
- some minor UI changes
|
||||
|
||||
5.08.2019
|
||||
|
||||
- made sure that if using an negative Gerber isolation diameter, the resulting Geometry object will use a tool with positive diameter
|
||||
- fixed bug that when isolating a Gerber file made out of a single polygon, an Recurrsion Exception was issued together with inability to create tbe isolation
|
||||
- when applying a new language if there are any changes in the current project, the app will offer to save the project before the reboot
|
||||
|
||||
3.08.2019
|
||||
|
||||
- added project name to the window title
|
||||
- fulfilled request: When saving a CNC file, if the file name is changed in the OS window, the new name does appear in the “Selected” (in name) and “Project” tabs (in cnc_job)
|
||||
- solved bug such that the app is not crashing when some apertures in the Gerber file have no geometry. More than that, now the apertures that have geometry elements are bolded as opposed to the ones without geometry for which the text is unbolded
|
||||
- merged a pull request with language changes for Russian translate
|
||||
- updated the other translations
|
||||
|
||||
31.07.2019
|
||||
|
||||
|
|
17
camlib.py
17
camlib.py
|
@ -543,6 +543,8 @@ class Geometry(object):
|
|||
|
||||
# the previously commented block is replaced with this block - regression - to solve the bug with multiple
|
||||
# isolation passes cutting from the copper features
|
||||
|
||||
geo_iso = []
|
||||
if offset == 0:
|
||||
if follow:
|
||||
geo_iso = self.follow_geometry
|
||||
|
@ -553,10 +555,19 @@ class Geometry(object):
|
|||
geo_iso = self.follow_geometry
|
||||
else:
|
||||
if corner is None:
|
||||
geo_iso = self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4))
|
||||
if type(self.solid_geometry) is list and len(self.solid_geometry) == 1:
|
||||
geo_iso = self.solid_geometry[0].buffer(offset, int(int(self.geo_steps_per_circle) / 4))
|
||||
else:
|
||||
for el in self.solid_geometry:
|
||||
geo_iso.append(el.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
|
||||
else:
|
||||
geo_iso = self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
join_style=corner)
|
||||
if type(self.solid_geometry) is list and len(self.solid_geometry) == 1:
|
||||
geo_iso = self.solid_geometry.buffer[0](offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
join_style=corner)
|
||||
else:
|
||||
for el in self.solid_geometry:
|
||||
geo_iso.append(el.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
join_style=corner))
|
||||
|
||||
# end of replaced block
|
||||
if follow:
|
||||
|
|
|
@ -837,7 +837,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.pref_tab_area = FCTab()
|
||||
self.pref_tab_area.setTabsClosable(False)
|
||||
self.pref_tab_area_tabBar = self.pref_tab_area.tabBar()
|
||||
self.pref_tab_area_tabBar.setStyleSheet("QTabBar::tab{width:90px;}")
|
||||
self.pref_tab_area_tabBar.setStyleSheet("QTabBar::tab{min-width:90px;}")
|
||||
self.pref_tab_area_tabBar.setExpanding(True)
|
||||
self.pref_tab_layout.addWidget(self.pref_tab_area)
|
||||
|
||||
|
@ -3148,13 +3148,13 @@ class GeneralPreferencesUI(QtWidgets.QWidget):
|
|||
self.setLayout(self.layout)
|
||||
|
||||
self.general_app_group = GeneralAppPrefGroupUI()
|
||||
self.general_app_group.setFixedWidth(290)
|
||||
self.general_app_group.setMinimumWidth(290)
|
||||
|
||||
self.general_gui_group = GeneralGUIPrefGroupUI()
|
||||
self.general_gui_group.setFixedWidth(250)
|
||||
self.general_gui_group.setMinimumWidth(250)
|
||||
|
||||
self.general_gui_set_group = GeneralGUISetGroupUI()
|
||||
self.general_gui_set_group.setFixedWidth(250)
|
||||
self.general_gui_set_group.setMinimumWidth(250)
|
||||
|
||||
self.layout.addWidget(self.general_app_group)
|
||||
self.layout.addWidget(self.general_gui_group)
|
||||
|
@ -3171,15 +3171,15 @@ class GerberPreferencesUI(QtWidgets.QWidget):
|
|||
self.setLayout(self.layout)
|
||||
|
||||
self.gerber_gen_group = GerberGenPrefGroupUI()
|
||||
self.gerber_gen_group.setFixedWidth(250)
|
||||
self.gerber_gen_group.setMinimumWidth(250)
|
||||
self.gerber_opt_group = GerberOptPrefGroupUI()
|
||||
self.gerber_opt_group.setFixedWidth(250)
|
||||
self.gerber_opt_group.setMinimumWidth(250)
|
||||
self.gerber_exp_group = GerberExpPrefGroupUI()
|
||||
self.gerber_exp_group.setFixedWidth(230)
|
||||
self.gerber_exp_group.setMinimumWidth(230)
|
||||
self.gerber_adv_opt_group = GerberAdvOptPrefGroupUI()
|
||||
self.gerber_adv_opt_group.setFixedWidth(200)
|
||||
self.gerber_adv_opt_group.setMinimumWidth(200)
|
||||
self.gerber_editor_group = GerberEditorPrefGroupUI()
|
||||
self.gerber_editor_group.setFixedWidth(200)
|
||||
self.gerber_editor_group.setMinimumWidth(200)
|
||||
|
||||
self.vlay = QtWidgets.QVBoxLayout()
|
||||
self.vlay.addWidget(self.gerber_opt_group)
|
||||
|
@ -3201,15 +3201,15 @@ class ExcellonPreferencesUI(QtWidgets.QWidget):
|
|||
self.setLayout(self.layout)
|
||||
|
||||
self.excellon_gen_group = ExcellonGenPrefGroupUI()
|
||||
self.excellon_gen_group.setFixedWidth(220)
|
||||
self.excellon_gen_group.setMinimumWidth(220)
|
||||
self.excellon_opt_group = ExcellonOptPrefGroupUI()
|
||||
self.excellon_opt_group.setFixedWidth(290)
|
||||
self.excellon_opt_group.setMinimumWidth(290)
|
||||
self.excellon_exp_group = ExcellonExpPrefGroupUI()
|
||||
self.excellon_exp_group.setFixedWidth(250)
|
||||
self.excellon_exp_group.setMinimumWidth(250)
|
||||
self.excellon_adv_opt_group = ExcellonAdvOptPrefGroupUI()
|
||||
self.excellon_adv_opt_group.setFixedWidth(250)
|
||||
self.excellon_adv_opt_group.setMinimumWidth(250)
|
||||
self.excellon_editor_group = ExcellonEditorPrefGroupUI()
|
||||
self.excellon_editor_group.setFixedWidth(260)
|
||||
self.excellon_editor_group.setMinimumWidth(260)
|
||||
|
||||
self.vlay = QtWidgets.QVBoxLayout()
|
||||
self.vlay.addWidget(self.excellon_opt_group)
|
||||
|
@ -3231,13 +3231,13 @@ class GeometryPreferencesUI(QtWidgets.QWidget):
|
|||
self.setLayout(self.layout)
|
||||
|
||||
self.geometry_gen_group = GeometryGenPrefGroupUI()
|
||||
self.geometry_gen_group.setFixedWidth(220)
|
||||
self.geometry_gen_group.setMinimumWidth(220)
|
||||
self.geometry_opt_group = GeometryOptPrefGroupUI()
|
||||
self.geometry_opt_group.setFixedWidth(300)
|
||||
self.geometry_opt_group.setMinimumWidth(300)
|
||||
self.geometry_adv_opt_group = GeometryAdvOptPrefGroupUI()
|
||||
self.geometry_adv_opt_group.setFixedWidth(270)
|
||||
self.geometry_adv_opt_group.setMinimumWidth(270)
|
||||
self.geometry_editor_group = GeometryEditorPrefGroupUI()
|
||||
self.geometry_editor_group.setFixedWidth(250)
|
||||
self.geometry_editor_group.setMinimumWidth(250)
|
||||
|
||||
self.layout.addWidget(self.geometry_gen_group)
|
||||
self.layout.addWidget(self.geometry_opt_group)
|
||||
|
@ -3313,11 +3313,11 @@ class CNCJobPreferencesUI(QtWidgets.QWidget):
|
|||
self.setLayout(self.layout)
|
||||
|
||||
self.cncjob_gen_group = CNCJobGenPrefGroupUI()
|
||||
self.cncjob_gen_group.setFixedWidth(320)
|
||||
self.cncjob_gen_group.setMinimumWidth(320)
|
||||
self.cncjob_opt_group = CNCJobOptPrefGroupUI()
|
||||
self.cncjob_opt_group.setFixedWidth(260)
|
||||
self.cncjob_opt_group.setMinimumWidth(260)
|
||||
self.cncjob_adv_opt_group = CNCJobAdvOptPrefGroupUI()
|
||||
self.cncjob_adv_opt_group.setFixedWidth(260)
|
||||
self.cncjob_adv_opt_group.setMinimumWidth(260)
|
||||
|
||||
self.layout.addWidget(self.cncjob_gen_group)
|
||||
self.layout.addWidget(self.cncjob_opt_group)
|
||||
|
|
|
@ -830,6 +830,13 @@ class FCTab(QtWidgets.QTabWidget):
|
|||
self.tabBar().setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
|
||||
|
||||
|
||||
# class FCTabBar(QtWidgets.QTabBar):
|
||||
# def tabSizeHint(self, index):
|
||||
# size =QtWidgets.QTabBar.tabSizeHint(self, index)
|
||||
# w = int(self.width()/self.count())
|
||||
# return QtCore.QSize(w, size.height())
|
||||
|
||||
|
||||
class FCDetachableTab(QtWidgets.QTabWidget):
|
||||
"""
|
||||
From here:
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue