diff --git a/FlatCAMApp.py b/FlatCAMApp.py index a0c2bd30..c84bfc4b 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -279,7 +279,7 @@ class App(QtCore.QObject): # Folder for user settings. if sys.platform == 'win32': - from win32com.shell import shell, shellcon + from win32comext.shell import shell, shellcon if platform.architecture()[0] == '32bit': App.log.debug("Win32!") else: @@ -3430,9 +3430,14 @@ class App(QtCore.QObject): obj_type = "Geometry" if cleanup is None: self.geo_editor.update_fcgeometry(edited_obj) - self.geo_editor.update_options(edited_obj) + # self.geo_editor.update_options(edited_obj) + self.geo_editor.deactivate() + # restore GUI to the Selected TAB + # Remove anything else in the GUI + self.ui.tool_scroll_area.takeWidget() + # update the geo object options so it is including the bounding box values try: xmin, ymin, xmax, ymax = edited_obj.bounds() @@ -3441,13 +3446,11 @@ class App(QtCore.QObject): edited_obj.options['xmax'] = xmax edited_obj.options['ymax'] = ymax except AttributeError as e: - self.inform.emit('[WARNING] %s' % - _("Object empty after edit.")) + self.inform.emit('[WARNING] %s' % _("Object empty after edit.")) log.debug("App.editor2object() --> Geometry --> %s" % str(e)) - # restore GUI to the Selected TAB - # Remove anything else in the GUI - self.ui.tool_scroll_area.takeWidget() + edited_obj.build_ui() + self.inform.emit('[success] %s' % _("Editor exited. Editor content saved.")) elif isinstance(edited_obj, FlatCAMGerber): obj_type = "Gerber" @@ -3468,6 +3471,8 @@ class App(QtCore.QObject): # a single Polygon, therefore we pass this pass + self.inform.emit('[success] %s' % _("Editor exited. Editor content saved.")) + # restore GUI to the Selected TAB # Remove anything else in the GUI self.ui.selected_scroll_area.takeWidget() @@ -3480,16 +3485,16 @@ class App(QtCore.QObject): self.exc_editor.deactivate() - # delete the old object (the source object) if it was an empty one - if len(edited_obj.drills) == 0 and len(edited_obj.slots) == 0: - old_name = edited_obj.options['name'] - self.collection.set_active(old_name) - self.collection.delete_active() - # restore GUI to the Selected TAB # Remove anything else in the GUI self.ui.tool_scroll_area.takeWidget() + # delete the old object (the source object) if it was an empty one + if len(edited_obj.drills) == 0 and len(edited_obj.slots) == 0: + old_name = edited_obj.options['name'] + self.collection.delete_by_name(name=old_name) + self.inform.emit('[success] %s' % _("Editor exited. Editor content saved.")) + else: self.inform.emit('[WARNING_NOTCL] %s' % _("Select a Gerber, Geometry or Excellon Object to update.")) @@ -3502,13 +3507,17 @@ class App(QtCore.QObject): self.ui.tool_scroll_area.setWidget(QtWidgets.QWidget()) self.ui.notebook.setTabText(2, "Tool") + self.inform.emit('[WARNING_NOTCL] %s' % _("Editor exited. Editor content was not saved.")) + if isinstance(edited_obj, FlatCAMGeometry): self.geo_editor.deactivate() + edited_obj.build_ui() elif isinstance(edited_obj, FlatCAMGerber): self.grb_editor.deactivate_grb_editor() + edited_obj.build_ui() elif isinstance(edited_obj, FlatCAMExcellon): self.exc_editor.deactivate() - # set focus on the project tab + edited_obj.build_ui() else: self.inform.emit('[WARNING_NOTCL] %s' % _("Select a Gerber, Geometry or Excellon Object to update.")) @@ -3516,8 +3525,8 @@ class App(QtCore.QObject): elif response == bt_cancel: return - edited_obj.set_ui(edited_obj.ui_type(decimals=self.decimals)) - edited_obj.build_ui() + # edited_obj.set_ui(edited_obj.ui_type(decimals=self.decimals)) + # edited_obj.build_ui() # Switch notebook to Selected page self.ui.notebook.setCurrentWidget(self.ui.selected_tab) else: @@ -3926,7 +3935,8 @@ class App(QtCore.QObject): json.dump(self.defaults, f_f_def_s, default=to_dict, indent=2, sort_keys=True) f_f_def_s.close() - # and then make the factory_defaults.FlatConfig file read_only so it can't be modified after creation. + # and then make the factory_defaults.FlatConfig file read_only + # so it can't be modified after creation. os.chmod(fact_def_file_path, S_IREAD | S_IRGRP | S_IROTH) except Exception as e: log.debug("App.load_defaults() -> deleting old factory defaults file -> %s" % str(e)) @@ -10362,7 +10372,7 @@ class App(QtCore.QObject): filename, _f = QtWidgets.QFileDialog.getSaveFileName( caption=_("Save Project As ..."), directory=('{l_save}/{proj}_{date}').format(l_save=str(self.get_last_save_folder()), date=self.date, - proj=_("Project")), + proj=_("Project")), filter=filter_ ) except TypeError: @@ -10416,8 +10426,8 @@ class App(QtCore.QObject): filename, _f = QtWidgets.QFileDialog.getSaveFileName( caption=_("Save Object as PDF ..."), directory=('{l_save}/{obj_name}_{date}').format(l_save=str(self.get_last_save_folder()), - obj_name=obj_name, - date=self.date), + obj_name=obj_name, + date=self.date), filter=filter_ ) except TypeError: @@ -11204,7 +11214,7 @@ class App(QtCore.QObject): # # ## Object creation # ## ret = self.new_object("gerber", name, obj_init, autoselected=False) if ret == 'fail': - self.inform.emit('[ERROR_NOTCL]%s' % _(' Open Gerber failed. Probable not a Gerber file.')) + self.inform.emit('[ERROR_NOTCL]%s' % _(' Open Gerber failed. Probable not a Gerber file.')) return 'fail' # Register recent file @@ -11218,11 +11228,11 @@ class App(QtCore.QObject): Opens an Excellon file, parses it and creates a new object for it in the program. Thread-safe. - :param outname: Name of the resulting object. None causes the - name to be that of the file. - :param filename: Excellon file filename - :type filename: str - :return: None + :param outname: Name of the resulting object. None causes the name to be that of the file. + :param filename: Excellon file filename + :type filename: str + :param plot: boolean, to plot or not the resulting object + :return: None """ App.log.debug("open_excellon()") diff --git a/ObjectCollection.py b/ObjectCollection.py index bf7c07dd..799d163c 100644 --- a/ObjectCollection.py +++ b/ObjectCollection.py @@ -645,6 +645,59 @@ class ObjectCollection(QtCore.QAbstractItemModel): if not self.get_list(): self.app.ui.splitter.setSizes([0, 1]) + def delete_by_name(self, name, select_project=True): + obj = self.get_by_name(name=name) + item = obj.item + group = self.group_items[obj.kind] + + group_index = self.index(group.row(), 0, QtCore.QModelIndex()) + item_index = self.index(item.row(), 0, group_index) + + deleted = item_index.internalPointer() + group = deleted.parent_item + + # some objects add a Tab on creation, close it here + for idx in range(self.app.ui.plot_tab_area.count()): + if self.app.ui.plot_tab_area.widget(idx).objectName() == deleted.obj.options['name']: + self.app.ui.plot_tab_area.removeTab(idx) + break + + # update the SHELL auto-completer model data + name = deleted.obj.options['name'] + try: + self.app.myKeywords.remove(name) + self.app.shell._edit.set_model_data(self.app.myKeywords) + # this is not needed any more because now the code editor is created on demand + # self.app.ui.code_editor.set_model_data(self.app.myKeywords) + except Exception as e: + log.debug( + "delete_active() --> Could not remove the old object name from auto-completer model list. %s" % str(e)) + + self.app.object_status_changed.emit(deleted.obj, 'delete', name) + + # ############ OBJECT DELETION FROM MODEL STARTS HERE #################### + self.beginRemoveRows(self.index(group.row(), 0, QtCore.QModelIndex()), deleted.row(), deleted.row()) + group.remove_child(deleted) + # after deletion of object store the current list of objects into the self.app.all_objects_list + self.app.all_objects_list = self.get_list() + self.endRemoveRows() + # ############ OBJECT DELETION FROM MODEL STOPS HERE #################### + + if self.app.is_legacy is False: + self.app.plotcanvas.redraw() + + if select_project: + # always go to the Project Tab after object deletion as it may be done with a shortcut key + self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab) + + self.app.should_we_save = True + + # decide if to show or hide the Notebook side of the screen + if self.app.defaults["global_project_autohide"] is True: + # hide the notebook if there are no objects in the collection + if not self.get_list(): + self.app.ui.splitter.setSizes([0, 1]) + def delete_all(self): FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_all()") diff --git a/README.md b/README.md index fc0ebf77..dcd8d762 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing. ================================================= +29.01.2020 + +- changes in how the Editor exit is handled +- small fix in some pywin32 imports + 28.01.2020 - some changes in Excellon Editor diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py index 1e621a9c..e2dc8bdb 100644 --- a/flatcamEditors/FlatCAMExcEditor.py +++ b/flatcamEditors/FlatCAMExcEditor.py @@ -3270,6 +3270,8 @@ class FlatCAMExcEditor(QtCore.QObject): self.new_slots, self.new_tools]}) + return self.edited_obj_name + def update_options(self, obj): try: if not obj.options: