Jelajahi Sumber

- unfortunately the fix for issue where while zooming the mouse cursor shape was not updated braked something in way that Matplotlib work with PyQt5, therefore I removed it

Marius Stanciu 6 tahun lalu
induk
melakukan
61e2792047
7 mengubah file dengan 169 tambahan dan 159 penghapusan
  1. 1 0
      FlatCAMApp.py
  2. 23 0
      FlatCAMCommon.py
  3. 4 4
      FlatCAMObj.py
  4. 16 13
      ObjectCollection.py
  5. 3 0
      README.md
  6. 121 141
      flatcamGUI/PlotCanvasLegacy.py
  7. 1 1
      flatcamGUI/VisPyPatches.py

+ 1 - 0
FlatCAMApp.py

@@ -11142,6 +11142,7 @@ class App(QtCore.QObject):
         self.kp = self.plotcanvas.graph_event_connect('key_press', self.ui.keyPressEvent)
 
         self.app_cursor = self.plotcanvas.new_cursor()
+
         if self.ui.grid_snap_btn.isChecked():
             self.app_cursor.enabled = True
         else:

+ 23 - 0
FlatCAMCommon.py

@@ -46,3 +46,26 @@ class LoudDict(dict):
         """
 
         self.callback = callback
+
+
+class FCSignal:
+    """
+    Taken from here: https://blog.abstractfactory.io/dynamic-signals-in-pyqt/
+    """
+
+    def __init__(self):
+        self.__subscribers = []
+
+    def emit(self, *args, **kwargs):
+        for subs in self.__subscribers:
+            subs(*args, **kwargs)
+
+    def connect(self, func):
+        self.__subscribers.append(func)
+
+    def disconnect(self, func):
+        try:
+            self.__subscribers.remove(func)
+        except ValueError:
+            print('Warning: function %s not removed '
+                  'from signal %s' % (func, self))

+ 4 - 4
FlatCAMObj.py

@@ -5756,9 +5756,8 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
             pass
         self.ui.annotation_cb.stateChanged.connect(self.on_annotation_change)
 
-        if self.app.is_legacy is False:
-            # set if to display text annotations
-            self.ui.annotation_cb.set_value(self.app.defaults["cncjob_annotation"])
+        # set if to display text annotations
+        self.ui.annotation_cb.set_value(self.app.defaults["cncjob_annotation"])
 
         # Show/Hide Advanced Options
         if self.app.defaults["global_app_level"] == 'b':
@@ -6244,7 +6243,8 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
             # self.plot(kind=kind)
             self.annotation.redraw()
         else:
-            self.inform.emit(_("Not available with the current Graphic Engine Legacy(2D)."))
+            kind = self.ui.cncplot_method_combo.get_value()
+            self.plot(kind=kind)
 
     def convert_units(self, units):
         log.debug("FlatCAMObj.FlatCAMECNCjob.convert_units()")

+ 16 - 13
ObjectCollection.py

@@ -605,30 +605,33 @@ class ObjectCollection(QtCore.QAbstractItemModel):
 
     def delete_all(self):
         FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_all()")
+        try:
+            self.app.all_objects_list.clear()
 
-        self.app.plotcanvas.redraw()
+            self.app.geo_editor.clear()
 
-        self.app.all_objects_list.clear()
+            self.app.exc_editor.clear()
 
-        self.app.geo_editor.clear()
+            self.app.dblsidedtool.reset_fields()
 
-        self.app.exc_editor.clear()
+            self.app.panelize_tool.reset_fields()
 
-        self.app.dblsidedtool.reset_fields()
+            self.app.cutout_tool.reset_fields()
 
-        self.app.panelize_tool.reset_fields()
+            self.app.film_tool.reset_fields()
 
-        self.app.cutout_tool.reset_fields()
+            self.beginResetModel()
 
-        self.app.film_tool.reset_fields()
+            self.checked_indexes = []
 
-        self.beginResetModel()
+            for group in self.root_item.child_items:
+                group.remove_children()
 
-        self.checked_indexes = []
-        for group in self.root_item.child_items:
-            group.remove_children()
+            self.endResetModel()
 
-        self.endResetModel()
+            self.app.plotcanvas.redraw()
+        except Exception as e:
+            log.debug("ObjectCollection.delete_all() --> %s" % str(e))
 
     def get_active(self):
         """

+ 3 - 0
README.md

@@ -16,6 +16,9 @@ CAD program, and create G-Code for Isolation routing.
 - in legacy graphic engine, fixed issue where immediately after changing the mouse cursor snapping the mouse cursor shape was not updated
 - in legacy graphic engine, fixed issue where while zooming the mouse cursor shape was not updated
 - in legacy graphic engine, fixed issue where immediately after panning finished the mouse cursor shape was not updated
+- unfortunately the fix for issue where while zooming the mouse cursor shape was not updated braked something in way that Matplotlib work with PyQt5, therefore I removed it
+- fixed a bug in legacy graphic engine: when doing the self.app.collection.delete_all() in new_project an app crash occurred
+- implemented the Annotation change in CNCJob Selected Tab
 
 23.09.2019
 

+ 121 - 141
flatcamGUI/PlotCanvasLegacy.py

@@ -10,14 +10,6 @@
 from PyQt5 import QtGui, QtCore, QtWidgets
 from PyQt5.QtCore import pyqtSignal
 
-# Prevent conflict with Qt5 and above.
-from matplotlib import use as mpl_use
-mpl_use("Qt5Agg")
-from matplotlib.figure import Figure
-from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
-from matplotlib.backends.backend_agg import FigureCanvasAgg
-from matplotlib.widgets import Cursor
-
 # needed for legacy mode
 # Used for solid polygons in Matplotlib
 from descartes.patch import PolygonPatch
@@ -25,14 +17,21 @@ from descartes.patch import PolygonPatch
 from shapely.geometry import Polygon, LineString, LinearRing, Point, MultiPolygon, MultiLineString
 
 import FlatCAMApp
+
 from copy import deepcopy
 import logging
-import traceback
 
 import gettext
 import FlatCAMTranslation as fcTranslate
 import builtins
 
+# Prevent conflict with Qt5 and above.
+from matplotlib import use as mpl_use
+mpl_use("Qt5Agg")
+from matplotlib.figure import Figure
+from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
+# from matplotlib.widgets import Cursor
+
 fcTranslate.apply_language('strings')
 if '_' not in builtins.__dict__:
     _ = gettext.gettext
@@ -78,7 +77,7 @@ class CanvasCache(QtCore.QObject):
         self.axes.set_xticks([])
         self.axes.set_yticks([])
 
-        self.canvas = FigureCanvasAgg(self.figure)
+        self.canvas = FigureCanvas(self.figure)
 
         self.cache = None
 
@@ -115,33 +114,6 @@ class CanvasCache(QtCore.QObject):
     #     log.debug("A new object is available. Should plot it!")
 
 
-class FigureCanvas(FigureCanvasQTAgg):
-    """
-    Reimplemented this so I can emit a signal when the idle drawing is finished and display the mouse shape
-    """
-
-    idle_drawing_finished = pyqtSignal()
-
-    def __init__(self, figure):
-        super().__init__(figure=figure)
-
-    def _draw_idle(self):
-        if self.height() < 0 or self.width() < 0:
-            self._draw_pending = False
-        if not self._draw_pending:
-            return
-        try:
-            self.draw()
-        except Exception:
-            # Uncaught exceptions are fatal for PyQt5, so catch them instead.
-            traceback.print_exc()
-        finally:
-            self._draw_pending = False
-
-            # I reimplemented this class only to launch this signal
-            self.idle_drawing_finished.emit()
-
-
 class PlotCanvasLegacy(QtCore.QObject):
     """
     Class handling the plotting area in the application.
@@ -151,6 +123,7 @@ class PlotCanvasLegacy(QtCore.QObject):
     # Request for new bitmap to display. The parameter
     # is a list with [xmin, xmax, ymin, ymax, zoom(optional)]
     update_screen_request = QtCore.pyqtSignal(list)
+
     double_click = QtCore.pyqtSignal(object)
 
     def __init__(self, container, app):
@@ -188,6 +161,7 @@ class PlotCanvasLegacy(QtCore.QObject):
 
         # The canvas is the top level container (FigureCanvasQTAgg)
         self.canvas = FigureCanvas(self.figure)
+
         self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus)
         self.canvas.setFocus()
         self.native = self.canvas
@@ -203,15 +177,17 @@ class PlotCanvasLegacy(QtCore.QObject):
         # Update every time the canvas is re-drawn.
         self.background = self.canvas.copy_from_bbox(self.axes.bbox)
 
+        # ################### NOT IMPLEMENTED YET - EXPERIMENTAL #######################
         # ## Bitmap Cache
-        self.cache = CanvasCache(self, self.app)
-        self.cache_thread = QtCore.QThread()
-        self.cache.moveToThread(self.cache_thread)
-        # super(PlotCanvas, self).connect(self.cache_thread, QtCore.SIGNAL("started()"), self.cache.run)
-        self.cache_thread.started.connect(self.cache.run)
-
-        self.cache_thread.start()
-        self.cache.new_screen.connect(self.on_new_screen)
+        # self.cache = CanvasCache(self, self.app)
+        # self.cache_thread = QtCore.QThread()
+        # self.cache.moveToThread(self.cache_thread)
+        # # super(PlotCanvas, self).connect(self.cache_thread, QtCore.SIGNAL("started()"), self.cache.run)
+        # self.cache_thread.started.connect(self.cache.run)
+        #
+        # self.cache_thread.start()
+        # self.cache.new_screen.connect(self.on_new_screen)
+        # ##############################################################################
 
         # Events
         self.mp = self.graph_event_connect('button_press_event', self.on_mouse_press)
@@ -226,11 +202,11 @@ class PlotCanvasLegacy(QtCore.QObject):
         # self.graph_event_connect('key_release_event', self.on_key_up)
         self.odr = self.graph_event_connect('draw_event', self.on_draw)
 
-        self.mouse = [0, 0]
         self.key = None
 
         self.pan_axes = []
         self.panning = False
+        self.mouse = [0, 0]
 
         # signal is the mouse is dragging
         self.is_dragging = False
@@ -238,9 +214,6 @@ class PlotCanvasLegacy(QtCore.QObject):
         # signal if there is a doubleclick
         self.is_dblclk = False
 
-        # pay attention, this signal should be connected only after the self.canvas and self.mouse is declared
-        self.canvas.idle_drawing_finished.connect(lambda: self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1]))
-
     def graph_event_connect(self, event_name, callback):
         """
         Attach an event handler to the canvas through the Matplotlib interface.
@@ -294,6 +267,31 @@ class PlotCanvasLegacy(QtCore.QObject):
             print(str(e))
         return c
 
+    def draw_cursor(self, x_pos, y_pos):
+        """
+        Draw a cursor at the mouse grid snapped position
+
+        :param x_pos: mouse x position
+        :param y_pos: mouse y position
+        :return:
+        """
+        # there is no point in drawing mouse cursor when panning as it jumps in a confusing way
+        if self.app.app_cursor.enabled is True and self.panning is False:
+            try:
+                x, y = self.app.geo_editor.snap(x_pos, y_pos)
+
+                # Pointer (snapped)
+                elements = self.axes.plot(x, y, 'k+', ms=40, mew=2, animated=True)
+                for el in elements:
+                    self.axes.draw_artist(el)
+            except Exception as e:
+                # this happen at app initialization since self.app.geo_editor does not exist yet
+                # I could reshuffle the object instantiating order but what's the point? I could crash something else
+                # and that's pythonic, too
+                pass
+
+        self.canvas.blit(self.axes.bbox)
+
     def clear_cursor(self, state):
 
         if state is True:
@@ -653,31 +651,6 @@ class PlotCanvasLegacy(QtCore.QObject):
 
         # self.canvas.blit(self.axes.bbox)
 
-    def draw_cursor(self, x_pos, y_pos):
-        """
-        Draw a cursor at the mouse grid snapped position
-
-        :param x_pos: mouse x position
-        :param y_pos: mouse y position
-        :return:
-        """
-        # there is no point in drawing mouse cursor when panning as it jumps in a confusing way
-        if self.app.app_cursor.enabled is True and self.panning is False:
-            try:
-                x, y = self.app.geo_editor.snap(x_pos, y_pos)
-
-                # Pointer (snapped)
-                elements = self.axes.plot(x, y, 'k+', ms=40, mew=2, animated=True)
-                for el in elements:
-                    self.axes.draw_artist(el)
-            except Exception as e:
-                # this happen at app initialization since self.app.geo_editor does not exist yet
-                # I could reshuffle the object instantiating order but what's the point? I could crash something else
-                # and that's pythonic, too
-                pass
-
-        self.canvas.blit(self.axes.bbox)
-
     def translate_coords(self, position):
         """
         This does not do much. It's just for code compatibility
@@ -750,66 +723,6 @@ class FakeCursor(QtCore.QObject):
         pass
 
 
-class MplCursor(Cursor):
-    """
-    Unfortunately this gets attached to the current axes and if a new axes is added
-    it will not be showed until that axes is deleted.
-    Not the kind of behavior needed here so I don't use it anymore.
-    """
-    def __init__(self, axes, color='red', linewidth=1):
-
-        super().__init__(ax=axes, useblit=True, color=color, linewidth=linewidth)
-        self._enabled = True
-
-        self.axes = axes
-        self.color = color
-        self.linewidth = linewidth
-
-        self.x = None
-        self.y = None
-
-    @property
-    def enabled(self):
-        return True if self._enabled else False
-
-    @enabled.setter
-    def enabled(self, value):
-        self._enabled = value
-        self.visible = self._enabled
-        self.canvas.draw()
-
-    def onmove(self, event):
-        pass
-
-    def set_data(self, event, pos):
-        """Internal event handler to draw the cursor when the mouse moves."""
-        self.x = pos[0]
-        self.y = pos[1]
-
-        if self.ignore(event):
-            return
-        if not self.canvas.widgetlock.available(self):
-            return
-        if event.inaxes != self.ax:
-            self.linev.set_visible(False)
-            self.lineh.set_visible(False)
-
-            if self.needclear:
-                self.canvas.draw()
-                self.needclear = False
-            return
-        self.needclear = True
-        if not self.visible:
-            return
-        self.linev.set_xdata((self.x, self.x))
-
-        self.lineh.set_ydata((self.y, self.y))
-        self.linev.set_visible(self.visible and self.vertOn)
-        self.lineh.set_visible(self.visible and self.horizOn)
-
-        self._update()
-
-
 class ShapeCollectionLegacy:
     """
     This will create the axes for each collection of shapes and will also
@@ -930,7 +843,10 @@ class ShapeCollectionLegacy:
         self.shape_id = 0
 
         self.axes.cla()
-        self.app.plotcanvas.auto_adjust_axes()
+        try:
+            self.app.plotcanvas.auto_adjust_axes()
+        except Exception as e:
+            log.debug("ShapeCollectionLegacy.clear() --> %s" % str(e))
 
         if update is True:
             self.redraw()
@@ -1013,12 +929,17 @@ class ShapeCollectionLegacy:
                         self.axes.plot(x, y, linespec, color=linecolor)
                     else:
                         path_num += 1
-                        if isinstance(local_shapes[element]['shape'], Polygon):
-                            self.axes.annotate(str(path_num), xy=local_shapes[element]['shape'].exterior.coords[0],
-                                               xycoords='data', fontsize=20)
-                        else:
-                            self.axes.annotate(str(path_num), xy=local_shapes[element]['shape'].coords[0],
-                                               xycoords='data', fontsize=20)
+                        if self.obj.ui.annotation_cb.get_value():
+                            if isinstance(local_shapes[element]['shape'], Polygon):
+                                self.axes.annotate(
+                                    str(path_num),
+                                    xy=local_shapes[element]['shape'].exterior.coords[0],
+                                    xycoords='data', fontsize=20)
+                            else:
+                                self.axes.annotate(
+                                    str(path_num),
+                                    xy=local_shapes[element]['shape'].coords[0],
+                                    xycoords='data', fontsize=20)
 
                         patch = PolygonPatch(local_shapes[element]['shape'],
                                              facecolor=local_shapes[element]['face_color'],
@@ -1108,3 +1029,62 @@ class ShapeCollectionLegacy:
             if self._visible is False:
                 self.redraw()
         self._visible = value
+
+# class MplCursor(Cursor):
+#     """
+#     Unfortunately this gets attached to the current axes and if a new axes is added
+#     it will not be showed until that axes is deleted.
+#     Not the kind of behavior needed here so I don't use it anymore.
+#     """
+#     def __init__(self, axes, color='red', linewidth=1):
+#
+#         super().__init__(ax=axes, useblit=True, color=color, linewidth=linewidth)
+#         self._enabled = True
+#
+#         self.axes = axes
+#         self.color = color
+#         self.linewidth = linewidth
+#
+#         self.x = None
+#         self.y = None
+#
+#     @property
+#     def enabled(self):
+#         return True if self._enabled else False
+#
+#     @enabled.setter
+#     def enabled(self, value):
+#         self._enabled = value
+#         self.visible = self._enabled
+#         self.canvas.draw()
+#
+#     def onmove(self, event):
+#         pass
+#
+#     def set_data(self, event, pos):
+#         """Internal event handler to draw the cursor when the mouse moves."""
+#         self.x = pos[0]
+#         self.y = pos[1]
+#
+#         if self.ignore(event):
+#             return
+#         if not self.canvas.widgetlock.available(self):
+#             return
+#         if event.inaxes != self.ax:
+#             self.linev.set_visible(False)
+#             self.lineh.set_visible(False)
+#
+#             if self.needclear:
+#                 self.canvas.draw()
+#                 self.needclear = False
+#             return
+#         self.needclear = True
+#         if not self.visible:
+#             return
+#         self.linev.set_xdata((self.x, self.x))
+#
+#         self.lineh.set_ydata((self.y, self.y))
+#         self.linev.set_visible(self.visible and self.vertOn)
+#         self.lineh.set_visible(self.visible and self.horizOn)
+#
+#         self._update()

+ 1 - 1
flatcamGUI/VisPyPatches.py

@@ -88,7 +88,7 @@ def apply_patches():
     def _get_tick_frac_labels(self):
         """Get the major ticks, minor ticks, and major labels"""
         minor_num = 4  # number of minor ticks per major division
-        if (self.axis.scale_type == 'linear'):
+        if self.axis.scale_type == 'linear':
             domain = self.axis.domain
             if domain[1] < domain[0]:
                 flip = True