Просмотр исходного кода

- finished adding in Geometry Editor a TreeWidget with the geometry shapes found in the edited object

Marius Stanciu 6 лет назад
Родитель
Сommit
fd0438842d
5 измененных файлов с 202 добавлено и 21 удалено
  1. 9 2
      FlatCAMApp.py
  2. 2 1
      README.md
  3. 1 1
      camlib.py
  4. 186 16
      flatcamEditors/FlatCAMGeoEditor.py
  5. 4 1
      flatcamGUI/GUIElements.py

+ 9 - 2
FlatCAMApp.py

@@ -3444,6 +3444,13 @@ class App(QtCore.QObject):
                             self.inform.emit('[WARNING] %s' %
                             self.inform.emit('[WARNING] %s' %
                                              _("Object empty after edit."))
                                              _("Object empty after edit."))
                             log.debug("App.editor2object() --> Geometry --> %s" % str(e))
                             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):
                     elif isinstance(edited_obj, FlatCAMGerber):
                         obj_type = "Gerber"
                         obj_type = "Gerber"
                         if cleanup is None:
                         if cleanup is None:
@@ -3494,8 +3501,7 @@ class App(QtCore.QObject):
                                          _("Select a Gerber, Geometry or Excellon Object to update."))
                                          _("Select a Gerber, Geometry or Excellon Object to update."))
                         return
                         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:
                 elif response == bt_no:
                     # clean the Tools Tab
                     # clean the Tools Tab
                     self.ui.tool_scroll_area.takeWidget()
                     self.ui.tool_scroll_area.takeWidget()
@@ -3514,6 +3520,7 @@ class App(QtCore.QObject):
                                          _("Select a Gerber, Geometry or Excellon Object to update."))
                                          _("Select a Gerber, Geometry or Excellon Object to update."))
                         return
                         return
                     edited_obj.set_ui(edited_obj.ui_type(decimals=self.decimals))
                     edited_obj.set_ui(edited_obj.ui_type(decimals=self.decimals))
+                    edited_obj.build_ui()
                     self.ui.notebook.setCurrentWidget(self.ui.selected_tab)
                     self.ui.notebook.setCurrentWidget(self.ui.selected_tab)
                 elif response == bt_cancel:
                 elif response == bt_cancel:
                     return
                     return

+ 2 - 1
README.md

@@ -15,7 +15,8 @@ CAD program, and create G-Code for Isolation routing.
 - more work in Punch Gerber Tool
 - 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
 - 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
 - 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
 24.02.2020
 
 

+ 1 - 1
camlib.py

@@ -5972,7 +5972,7 @@ class FlatCAMRTreeStorage(FlatCAMRTree):
         self.objects.append(obj)
         self.objects.append(obj)
         idx = len(self.objects) - 1
         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
         # there seem to be plans to re-introduce the feature in
         # version 2.0. For now, we will index using the object's id,
         # version 2.0. For now, we will index using the object's id,
         # but it's important to remember that shapely geometry is
         # but it's important to remember that shapely geometry is

+ 186 - 16
flatcamEditors/FlatCAMGeoEditor.py

@@ -18,7 +18,7 @@ from camlib import distance, arc, three_point_circle, Geometry, FlatCAMRTreeStor
 from FlatCAMTool import FlatCAMTool
 from FlatCAMTool import FlatCAMTool
 from flatcamGUI.ObjectUI import RadioSet
 from flatcamGUI.ObjectUI import RadioSet
 from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
 from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
-    FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog
+    FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog, FCTree
 from flatcamParsers.ParseFont import *
 from flatcamParsers.ParseFont import *
 import FlatCAMApp
 import FlatCAMApp
 
 
@@ -2494,8 +2494,29 @@ class FCSelect(DrawTool):
                     self.draw_app.selected = []
                     self.draw_app.selected = []
                     self.draw_app.selected.append(obj_to_add)
                     self.draw_app.selected.append(obj_to_add)
         except Exception as e:
         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 ""
         return ""
 
 
     def clean_up(self):
     def clean_up(self):
@@ -3126,6 +3147,9 @@ class FCTransform(FCShapeTool):
 # ###############################################
 # ###############################################
 class FlatCAMGeoEditor(QtCore.QObject):
 class FlatCAMGeoEditor(QtCore.QObject):
 
 
+    # will emit the name of the object that was just selected
+    item_selected = QtCore.pyqtSignal(str)
+
     transform_complete = QtCore.pyqtSignal()
     transform_complete = QtCore.pyqtSignal()
 
 
     draw_shape_idx = -1
     draw_shape_idx = -1
@@ -3140,6 +3164,47 @@ class FlatCAMGeoEditor(QtCore.QObject):
         self.canvas = app.plotcanvas
         self.canvas = app.plotcanvas
         self.decimals = app.decimals
         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("<font size=5><b>%s</b></font>" % _('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
         # ## Toolbar events and properties
         self.tools = {
         self.tools = {
             "select": {"button": self.app.ui.geo_select_btn,
             "select": {"button": self.app.ui.geo_select_btn,
@@ -3346,6 +3411,13 @@ class FlatCAMGeoEditor(QtCore.QObject):
         self.units = self.app.defaults['units'].upper()
         self.units = self.app.defaults['units'].upper()
         self.decimals = self.app.decimals
         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):
     def build_ui(self, first_run=None):
 
 
         # try:
         # try:
@@ -3353,8 +3425,56 @@ class FlatCAMGeoEditor(QtCore.QObject):
         #     self.apertures_table.itemChanged.disconnect()
         #     self.apertures_table.itemChanged.disconnect()
         # except (TypeError, AttributeError):
         # except (TypeError, AttributeError):
         #     pass
         #     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
         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):
     def activate(self):
         # adjust the status of the menu entries related to the editor
         # adjust the status of the menu entries related to the editor
         self.app.ui.menueditedit.setDisabled(True)
         self.app.ui.menueditedit.setDisabled(True)
@@ -3403,12 +3523,22 @@ class FlatCAMGeoEditor(QtCore.QObject):
 
 
         # Tell the App that the editor is active
         # Tell the App that the editor is active
         self.editor_active = True
         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...")
         log.debug("Finished activating the Geometry Editor...")
 
 
     def deactivate(self):
     def deactivate(self):
         try:
         try:
             QtGui.QGuiApplication.restoreOverrideCursor()
             QtGui.QGuiApplication.restoreOverrideCursor()
-        except Exception as e:
+        except Exception:
             pass
             pass
 
 
         # adjust the status of the menu entries related to the editor
         # 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.e_editor_cmenu.menuAction().setVisible(False)
         self.app.ui.g_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:
         # try:
         #     # re-enable all the widgets in the Selected Tab that were disabled after entering in Edit Geometry Mode
         #     # 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)
         #     sel_tab_widget_list = self.app.ui.selected_tab.findChildren(QtWidgets.QWidget)
@@ -3483,6 +3626,10 @@ class FlatCAMGeoEditor(QtCore.QObject):
         # Show original geometry
         # Show original geometry
         if self.fcgeometry:
         if self.fcgeometry:
             self.fcgeometry.visible = True
             self.fcgeometry.visible = True
+
+        # hide the UI
+        self.geo_frame.hide()
+
         log.debug("Finished deactivating the Geometry Editor...")
         log.debug("Finished deactivating the Geometry Editor...")
 
 
     def connect_canvas_event_handlers(self):
     def connect_canvas_event_handlers(self):
@@ -3684,6 +3831,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
             self.utility.append(shape)
             self.utility.append(shape)
         else:
         else:
             self.storage.insert(shape)  # TODO: Check performance
             self.storage.insert(shape)  # TODO: Check performance
+            self.build_ui()
 
 
     def delete_utility_geometry(self):
     def delete_utility_geometry(self):
         # for_deletion = [shape for shape in self.shape_buffer if shape.utility]
         # for_deletion = [shape for shape in self.shape_buffer if shape.utility]
@@ -3724,6 +3872,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
         self.deactivate()
         self.deactivate()
         self.activate()
         self.activate()
 
 
+        self.set_ui()
+
         # Hide original geometry
         # Hide original geometry
         self.fcgeometry = fcgeometry
         self.fcgeometry = fcgeometry
         fcgeometry.visible = False
         fcgeometry.visible = False
@@ -3845,7 +3995,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
 
 
         self.pos = self.canvas.translate_coords(event_pos)
         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])
             self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
         else:
         else:
             self.pos = (self.pos[0], self.pos[1])
             self.pos = (self.pos[0], self.pos[1])
@@ -3925,7 +4075,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
             return
             return
 
 
         # ### Snap coordinates ###
         # ### Snap coordinates ###
-        if self.app.grid_status() == True:
+        if self.app.grid_status():
             x, y = self.snap(x, y)
             x, y = self.snap(x, y)
 
 
             # Update cursor
             # 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
         # update the position label in the infobar since the APP mouse event handlers are disconnected
         self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp;   "
         self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp;   "
-                                       "<b>Y</b>: %.4f" % (x, y))
+                                           "<b>Y</b>: %.4f" % (x, y))
 
 
         if self.pos is None:
         if self.pos is None:
             self.pos = (0, 0)
             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
         # update the reference position label in the infobar since the APP mouse event handlers are disconnected
         self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp;  <b>Dy</b>: "
         self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp;  <b>Dy</b>: "
-                                           "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
+                                               "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
 
 
         if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser):
         if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser):
             pass
             pass
@@ -3961,8 +4111,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
             self.app.delete_selection_shape()
             self.app.delete_selection_shape()
             if dx < 0:
             if dx < 0:
                 self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y),
                 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
                 self.app.selection_type = False
             else:
             else:
                 self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y))
                 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.app.inform.emit(msg)
                     self.replot()
                     self.replot()
             elif event.button == right_button:  # right click
             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:
                     if self.in_action is False:
                         try:
                         try:
                             QtGui.QGuiApplication.restoreOverrideCursor()
                             QtGui.QGuiApplication.restoreOverrideCursor()
-                        except Exception as e:
+                        except Exception:
                             pass
                             pass
 
 
                         if self.active_tool.complete is False and not isinstance(self.active_tool, FCSelect):
                         if self.active_tool.complete is False and not isinstance(self.active_tool, FCSelect):
                             self.active_tool.complete = True
                             self.active_tool.complete = True
                             self.in_action = False
                             self.in_action = False
                             self.delete_utility_geometry()
                             self.delete_utility_geometry()
-                            self.app.inform.emit('[success] %s' %
-                                                 _("Done."))
+                            self.app.inform.emit('[success] %s' % _("Done."))
                             self.select_tool('select')
                             self.select_tool('select')
                         else:
                         else:
                             self.app.cursor = QtGui.QCursor()
                             self.app.cursor = QtGui.QCursor()
@@ -4037,8 +4186,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
                             self.active_tool.make()
                             self.active_tool.make()
                             if self.active_tool.complete:
                             if self.active_tool.complete:
                                 self.on_shape_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)
                                 self.select_tool(self.active_tool.name)
         except Exception as e:
         except Exception as e:
             log.warning("FLatCAMGeoEditor.on_geo_click_release() --> Error: %s" % str(e))
             log.warning("FLatCAMGeoEditor.on_geo_click_release() --> Error: %s" % str(e))
@@ -4082,6 +4230,27 @@ class FlatCAMGeoEditor(QtCore.QObject):
             self.selected = []
             self.selected = []
             self.selected = sel_objects_list
             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()
         self.replot()
 
 
     def draw_utility_geometry(self, geo):
     def draw_utility_geometry(self, geo):
@@ -4131,6 +4300,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
         for shape in tempref:
         for shape in tempref:
             self.delete_shape(shape)
             self.delete_shape(shape)
         self.selected = []
         self.selected = []
+        self.build_ui()
 
 
     def delete_shape(self, shape):
     def delete_shape(self, shape):
 
 

+ 4 - 1
flatcamGUI/GUIElements.py

@@ -154,7 +154,7 @@ class RadioSet(QtWidgets.QWidget):
 
 
 class FCTree(QtWidgets.QTreeWidget):
 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)
         super(FCTree, self).__init__(parent)
 
 
         self.setColumnCount(columns)
         self.setColumnCount(columns)
@@ -162,6 +162,9 @@ class FCTree(QtWidgets.QTreeWidget):
         self.header().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
         self.header().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
         self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Expanding)
         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):
     def addParent(self, parent, title, expanded=False, color=None, font=None):
         item = QtWidgets.QTreeWidgetItem(parent, [title])
         item = QtWidgets.QTreeWidgetItem(parent, [title])
         item.setChildIndicatorPolicy(QtWidgets.QTreeWidgetItem.ShowIndicator)
         item.setChildIndicatorPolicy(QtWidgets.QTreeWidgetItem.ShowIndicator)