diff --git a/FlatCAMApp.py b/FlatCAMApp.py
index db4c9ad1..1a228bf9 100644
--- a/FlatCAMApp.py
+++ b/FlatCAMApp.py
@@ -3444,6 +3444,13 @@ class App(QtCore.QObject):
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()
+ # Switch notebook to Selected page
+ self.ui.notebook.setCurrentWidget(self.ui.selected_tab)
+
elif isinstance(edited_obj, FlatCAMGerber):
obj_type = "Gerber"
if cleanup is None:
@@ -3494,8 +3501,7 @@ class App(QtCore.QObject):
_("Select a Gerber, Geometry or Excellon Object to update."))
return
- self.inform.emit('[selected] %s %s' %
- (obj_type, _("is updated, returning to App...")))
+ self.inform.emit('[selected] %s %s' % (obj_type, _("is updated, returning to App...")))
elif response == bt_no:
# clean the Tools Tab
self.ui.tool_scroll_area.takeWidget()
@@ -3514,6 +3520,7 @@ class App(QtCore.QObject):
_("Select a Gerber, Geometry or Excellon Object to update."))
return
edited_obj.set_ui(edited_obj.ui_type(decimals=self.decimals))
+ edited_obj.build_ui()
self.ui.notebook.setCurrentWidget(self.ui.selected_tab)
elif response == bt_cancel:
return
diff --git a/README.md b/README.md
index ed74004a..e3dfaf54 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,8 @@ CAD program, and create G-Code for Isolation routing.
- more work in Punch Gerber Tool
- the Jump To popup window will now autoselect the LineEdit therefore no more need for an extra click after launching the function
- made some structural changes in Properties Tool
-- started t omake some changs in Geometry Editor
+- started to make some changes in Geometry Editor
+- finished adding in Geometry Editor a TreeWidget with the geometry shapes found in the edited object
24.02.2020
diff --git a/camlib.py b/camlib.py
index 063478b1..d234dc90 100644
--- a/camlib.py
+++ b/camlib.py
@@ -5972,7 +5972,7 @@ class FlatCAMRTreeStorage(FlatCAMRTree):
self.objects.append(obj)
idx = len(self.objects) - 1
- # Note: Shapely objects are not hashable any more, althought
+ # Note: Shapely objects are not hashable any more, although
# there seem to be plans to re-introduce the feature in
# version 2.0. For now, we will index using the object's id,
# but it's important to remember that shapely geometry is
diff --git a/flatcamEditors/FlatCAMGeoEditor.py b/flatcamEditors/FlatCAMGeoEditor.py
index 340c61bc..7a5a63c6 100644
--- a/flatcamEditors/FlatCAMGeoEditor.py
+++ b/flatcamEditors/FlatCAMGeoEditor.py
@@ -18,7 +18,7 @@ from camlib import distance, arc, three_point_circle, Geometry, FlatCAMRTreeStor
from FlatCAMTool import FlatCAMTool
from flatcamGUI.ObjectUI import RadioSet
from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
- FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog
+ FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog, FCTree
from flatcamParsers.ParseFont import *
import FlatCAMApp
@@ -2494,8 +2494,29 @@ class FCSelect(DrawTool):
self.draw_app.selected = []
self.draw_app.selected.append(obj_to_add)
except Exception as e:
- log.error("[ERROR] Something went bad. %s" % str(e))
- raise
+ log.error("[ERROR] FlatCAMGeoEditor.FCSelect.click_release() -> Something went bad. %s" % str(e))
+
+ # if selection is done on canvas update the Tree in Selected Tab with the selection
+ try:
+ self.draw_app.tw.itemSelectionChanged.disconnect(self.draw_app.on_tree_selection_change)
+ except (AttributeError, TypeError):
+ pass
+
+ self.draw_app.tw.selectionModel().clearSelection()
+ for sel_shape in self.draw_app.selected:
+ iterator = QtWidgets.QTreeWidgetItemIterator(self.draw_app.tw)
+ while iterator.value():
+ item = iterator.value()
+ try:
+ if int(item.text(1)) == id(sel_shape):
+ item.setSelected(True)
+ except ValueError:
+ pass
+
+ iterator += 1
+
+ self.draw_app.tw.itemSelectionChanged.connect(self.draw_app.on_tree_selection_change)
+
return ""
def clean_up(self):
@@ -3126,6 +3147,9 @@ class FCTransform(FCShapeTool):
# ###############################################
class FlatCAMGeoEditor(QtCore.QObject):
+ # will emit the name of the object that was just selected
+ item_selected = QtCore.pyqtSignal(str)
+
transform_complete = QtCore.pyqtSignal()
draw_shape_idx = -1
@@ -3140,6 +3164,47 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.canvas = app.plotcanvas
self.decimals = app.decimals
+ self.geo_edit_widget = QtWidgets.QWidget()
+ # ## Box for custom widgets
+ # This gets populated in offspring implementations.
+ layout = QtWidgets.QVBoxLayout()
+ self.geo_edit_widget.setLayout(layout)
+
+ # add a frame and inside add a vertical box layout. Inside this vbox layout I add all the Drills widgets
+ # this way I can hide/show the frame
+ self.geo_frame = QtWidgets.QFrame()
+ self.geo_frame.setContentsMargins(0, 0, 0, 0)
+ layout.addWidget(self.geo_frame)
+ self.tools_box = QtWidgets.QVBoxLayout()
+ self.tools_box.setContentsMargins(0, 0, 0, 0)
+ self.geo_frame.setLayout(self.tools_box)
+
+ # ## Page Title box (spacing between children)
+ self.title_box = QtWidgets.QHBoxLayout()
+ self.tools_box.addLayout(self.title_box)
+
+ # ## Page Title icon
+ pixmap = QtGui.QPixmap(self.app.resource_location + '/flatcam_icon32.png')
+ self.icon = QtWidgets.QLabel()
+ self.icon.setPixmap(pixmap)
+ self.title_box.addWidget(self.icon, stretch=0)
+
+ # ## Title label
+ self.title_label = QtWidgets.QLabel("%s" % _('Geometry Editor'))
+ self.title_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+ self.title_box.addWidget(self.title_label, stretch=1)
+ self.title_box.addWidget(QtWidgets.QLabel(''))
+
+ self.tw = FCTree(extended_sel=True)
+ self.tools_box.addWidget(self.tw)
+
+ self.geo_font = QtGui.QFont()
+ self.geo_font.setBold(True)
+
+ parent = self.tw.invisibleRootItem()
+ self.geo_parent = self.tw.addParent(
+ parent, _('Geometry Elements'), expanded=True, color=QtGui.QColor("#000000"), font=self.geo_font)
+
# ## Toolbar events and properties
self.tools = {
"select": {"button": self.app.ui.geo_select_btn,
@@ -3346,6 +3411,13 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.units = self.app.defaults['units'].upper()
self.decimals = self.app.decimals
+ # Remove anything else in the GUI Selected Tab
+ self.app.ui.selected_scroll_area.takeWidget()
+ # Put ourselves in the GUI Selected Tab
+ self.app.ui.selected_scroll_area.setWidget(self.geo_edit_widget)
+ # Switch notebook to Selected page
+ self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
+
def build_ui(self, first_run=None):
# try:
@@ -3353,8 +3425,56 @@ class FlatCAMGeoEditor(QtCore.QObject):
# self.apertures_table.itemChanged.disconnect()
# except (TypeError, AttributeError):
# pass
+
+ iterator = QtWidgets.QTreeWidgetItemIterator(self.geo_parent)
+ to_delete = list()
+ while iterator.value():
+ item = iterator.value()
+ to_delete.append(item)
+ iterator += 1
+ for it in to_delete:
+ self.geo_parent.removeChild(it)
+
+ for elem in self.storage.get_objects():
+ geo_type = type(elem.geo)
+ title = None
+ if geo_type is LinearRing:
+ title = _('ID Ring')
+ elif geo_type is LineString:
+ title = _('ID Line')
+ elif geo_type is Polygon:
+ title = _('ID Polygon')
+ elif geo_type is MultiLineString:
+ title = _('ID Multi-Line')
+ elif geo_type is MultiPolygon:
+ title = _('ID Multi-Polygon')
+
+ self.tw.addChild(
+ self.geo_parent,
+ [
+ '%s:' % title,
+ str(id(elem))
+ ],
+ True,
+ font=self.geo_font,
+ font_items=1
+ )
+
+ def on_geo_elem_selected(self):
pass
+ def on_tree_selection_change(self):
+ self.selected = list()
+ selected_tree_items = self.tw.selectedItems()
+ for sel in selected_tree_items:
+ for obj_shape in self.storage.get_objects():
+ try:
+ if id(obj_shape) == int(sel.text(1)):
+ self.selected.append(obj_shape)
+ except ValueError:
+ pass
+ self.replot()
+
def activate(self):
# adjust the status of the menu entries related to the editor
self.app.ui.menueditedit.setDisabled(True)
@@ -3403,12 +3523,22 @@ class FlatCAMGeoEditor(QtCore.QObject):
# Tell the App that the editor is active
self.editor_active = True
+
+ self.item_selected.connect(self.on_geo_elem_selected)
+
+ # ## GUI Events
+ self.tw.itemSelectionChanged.connect(self.on_tree_selection_change)
+ # self.tw.keyPressed.connect(self.app.ui.keyPressEvent)
+ # self.tw.customContextMenuRequested.connect(self.on_menu_request)
+
+ self.geo_frame.show()
+
log.debug("Finished activating the Geometry Editor...")
def deactivate(self):
try:
QtGui.QGuiApplication.restoreOverrideCursor()
- except Exception as e:
+ except Exception:
pass
# adjust the status of the menu entries related to the editor
@@ -3472,6 +3602,19 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.ui.e_editor_cmenu.menuAction().setVisible(False)
self.app.ui.g_editor_cmenu.menuAction().setVisible(False)
+ try:
+ self.item_selected.disconnect()
+ except (AttributeError, TypeError):
+ pass
+
+ try:
+ # ## GUI Events
+ self.tw.itemSelectionChanged.disconnect(self.on_tree_selection_change)
+ # self.tw.keyPressed.connect(self.app.ui.keyPressEvent)
+ # self.tw.customContextMenuRequested.connect(self.on_menu_request)
+ except (AttributeError, TypeError):
+ pass
+
# try:
# # re-enable all the widgets in the Selected Tab that were disabled after entering in Edit Geometry Mode
# sel_tab_widget_list = self.app.ui.selected_tab.findChildren(QtWidgets.QWidget)
@@ -3483,6 +3626,10 @@ class FlatCAMGeoEditor(QtCore.QObject):
# Show original geometry
if self.fcgeometry:
self.fcgeometry.visible = True
+
+ # hide the UI
+ self.geo_frame.hide()
+
log.debug("Finished deactivating the Geometry Editor...")
def connect_canvas_event_handlers(self):
@@ -3684,6 +3831,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.utility.append(shape)
else:
self.storage.insert(shape) # TODO: Check performance
+ self.build_ui()
def delete_utility_geometry(self):
# for_deletion = [shape for shape in self.shape_buffer if shape.utility]
@@ -3724,6 +3872,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.deactivate()
self.activate()
+ self.set_ui()
+
# Hide original geometry
self.fcgeometry = fcgeometry
fcgeometry.visible = False
@@ -3845,7 +3995,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.pos = self.canvas.translate_coords(event_pos)
- if self.app.grid_status() == True:
+ if self.app.grid_status():
self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
else:
self.pos = (self.pos[0], self.pos[1])
@@ -3925,7 +4075,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
return
# ### Snap coordinates ###
- if self.app.grid_status() == True:
+ if self.app.grid_status():
x, y = self.snap(x, y)
# Update cursor
@@ -3939,7 +4089,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
# update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.position_label.setText(" X: %.4f "
- "Y: %.4f" % (x, y))
+ "Y: %.4f" % (x, y))
if self.pos is None:
self.pos = (0, 0)
@@ -3948,7 +4098,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
# update the reference position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.rel_position_label.setText("Dx: %.4f Dy: "
- "%.4f " % (dx, dy))
+ "%.4f " % (dx, dy))
if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser):
pass
@@ -3961,8 +4111,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.delete_selection_shape()
if dx < 0:
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y),
- color=self.app.defaults["global_alt_sel_line"],
- face_color=self.app.defaults['global_alt_sel_fill'])
+ color=self.app.defaults["global_alt_sel_line"],
+ face_color=self.app.defaults['global_alt_sel_fill'])
self.app.selection_type = False
else:
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y))
@@ -4011,19 +4161,18 @@ class FlatCAMGeoEditor(QtCore.QObject):
# self.app.inform.emit(msg)
self.replot()
elif event.button == right_button: # right click
- if self.app.ui.popMenu.mouse_is_panning == False:
+ if self.app.ui.popMenu.mouse_is_panning is False:
if self.in_action is False:
try:
QtGui.QGuiApplication.restoreOverrideCursor()
- except Exception as e:
+ except Exception:
pass
if self.active_tool.complete is False and not isinstance(self.active_tool, FCSelect):
self.active_tool.complete = True
self.in_action = False
self.delete_utility_geometry()
- self.app.inform.emit('[success] %s' %
- _("Done."))
+ self.app.inform.emit('[success] %s' % _("Done."))
self.select_tool('select')
else:
self.app.cursor = QtGui.QCursor()
@@ -4037,8 +4186,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.active_tool.make()
if self.active_tool.complete:
self.on_shape_complete()
- self.app.inform.emit('[success] %s' %
- _("Done."))
+ self.app.inform.emit('[success] %s' % _("Done."))
self.select_tool(self.active_tool.name)
except Exception as e:
log.warning("FLatCAMGeoEditor.on_geo_click_release() --> Error: %s" % str(e))
@@ -4082,6 +4230,27 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.selected = []
self.selected = sel_objects_list
+ # if selection is done on canvas update the Tree in Selected Tab with the selection
+ try:
+ self.tw.itemSelectionChanged.disconnect(self.on_tree_selection_change)
+ except (AttributeError, TypeError):
+ pass
+
+ self.tw.selectionModel().clearSelection()
+ for sel_shape in self.selected:
+ iterator = QtWidgets.QTreeWidgetItemIterator(self.tw)
+ while iterator.value():
+ item = iterator.value()
+ try:
+ if int(item.text(1)) == id(sel_shape):
+ item.setSelected(True)
+ except ValueError:
+ pass
+
+ iterator += 1
+
+ self.tw.itemSelectionChanged.connect(self.on_tree_selection_change)
+
self.replot()
def draw_utility_geometry(self, geo):
@@ -4131,6 +4300,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
for shape in tempref:
self.delete_shape(shape)
self.selected = []
+ self.build_ui()
def delete_shape(self, shape):
diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py
index a136e16c..b9f17d9e 100644
--- a/flatcamGUI/GUIElements.py
+++ b/flatcamGUI/GUIElements.py
@@ -154,7 +154,7 @@ class RadioSet(QtWidgets.QWidget):
class FCTree(QtWidgets.QTreeWidget):
- def __init__(self, parent=None, columns=2, header_hidden=True):
+ def __init__(self, parent=None, columns=2, header_hidden=True, extended_sel=False):
super(FCTree, self).__init__(parent)
self.setColumnCount(columns)
@@ -162,6 +162,9 @@ class FCTree(QtWidgets.QTreeWidget):
self.header().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Expanding)
+ if extended_sel:
+ self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
+
def addParent(self, parent, title, expanded=False, color=None, font=None):
item = QtWidgets.QTreeWidgetItem(parent, [title])
item.setChildIndicatorPolicy(QtWidgets.QTreeWidgetItem.ShowIndicator)