- fixed a bug in milling holes due of a message wrongly formatted
This commit is contained in:
@@ -2813,10 +2813,13 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
|||||||
|
|
||||||
for tool in tools:
|
for tool in tools:
|
||||||
if tooldia > self.tools[tool]["C"]:
|
if tooldia > self.tools[tool]["C"]:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s %s: %s' % (
|
self.app.inform.emit(
|
||||||
_("Milling tool for DRILLS is larger than hole size. Cancelled.",
|
'[ERROR_NOTCL] %s %s: %s' % (
|
||||||
str(tool))
|
_("Milling tool for DRILLS is larger than hole size. Cancelled."),
|
||||||
))
|
_("Tool"),
|
||||||
|
str(tool)
|
||||||
|
)
|
||||||
|
)
|
||||||
return False, "Error: Milling tool is larger than hole."
|
return False, "Error: Milling tool is larger than hole."
|
||||||
|
|
||||||
def geo_init(geo_obj, app_obj):
|
def geo_init(geo_obj, app_obj):
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ CAD program, and create G-Code for Isolation routing.
|
|||||||
|
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
17.10.2019
|
||||||
|
|
||||||
|
- fixed a bug in milling holes due of a message wrongly formatted
|
||||||
|
|
||||||
16.10.2019
|
16.10.2019
|
||||||
|
|
||||||
- small update to Romanian translation files
|
- small update to Romanian translation files
|
||||||
|
|||||||
@@ -12,14 +12,17 @@ class Polygon(object):
|
|||||||
self.context = context
|
self.context = context
|
||||||
else:
|
else:
|
||||||
self.context = getattr(context, '__geo_interface__', context)
|
self.context = getattr(context, '__geo_interface__', context)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def geom_type(self):
|
def geom_type(self):
|
||||||
return (getattr(self.context, 'geom_type', None)
|
return (getattr(self.context, 'geom_type', None)
|
||||||
or self.context['type'])
|
or self.context['type'])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def exterior(self):
|
def exterior(self):
|
||||||
return (getattr(self.context, 'exterior', None)
|
return (getattr(self.context, 'exterior', None)
|
||||||
or self.context['coordinates'][0])
|
or self.context['coordinates'][0])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def interiors(self):
|
def interiors(self):
|
||||||
value = getattr(self.context, 'interiors', None)
|
value = getattr(self.context, 'interiors', None)
|
||||||
|
|||||||
@@ -562,7 +562,6 @@ class FCSlotArray(FCShapeTool):
|
|||||||
_("To add an Slot Array first select a tool in Tool Table"))
|
_("To add an Slot Array first select a tool in Tool Table"))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
QtGui.QGuiApplication.restoreOverrideCursor()
|
QtGui.QGuiApplication.restoreOverrideCursor()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -1012,7 +1011,6 @@ class FCDrillResize(FCShapeTool):
|
|||||||
|
|
||||||
sel_shapes_to_be_deleted.append(select_shape)
|
sel_shapes_to_be_deleted.append(select_shape)
|
||||||
|
|
||||||
|
|
||||||
# a hack to make the tool_table display more drills/slots per diameter when shape(drill/slot)
|
# a hack to make the tool_table display more drills/slots per diameter when shape(drill/slot)
|
||||||
# is added.
|
# is added.
|
||||||
# self.points_edit it's only useful first time when we load the data into the storage
|
# self.points_edit it's only useful first time when we load the data into the storage
|
||||||
@@ -3090,7 +3088,6 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||||||
# element[1] of the tuple is a list of coordinates (a tuple themselves)
|
# element[1] of the tuple is a list of coordinates (a tuple themselves)
|
||||||
ordered_edited_points = sorted(zip(edited_points.keys(), edited_points.values()))
|
ordered_edited_points = sorted(zip(edited_points.keys(), edited_points.values()))
|
||||||
|
|
||||||
|
|
||||||
current_tool = 0
|
current_tool = 0
|
||||||
for tool_dia in ordered_edited_points:
|
for tool_dia in ordered_edited_points:
|
||||||
current_tool += 1
|
current_tool += 1
|
||||||
@@ -3214,7 +3211,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_("There are no Tools definitions in the file. Aborting Excellon creation.")
|
_("There are no Tools definitions in the file. Aborting Excellon creation.")
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
msg = '[ERROR] %s' % \
|
msg = '[ERROR] %s' % \
|
||||||
_("An internal error has ocurred. See Shell.\n")
|
_("An internal error has ocurred. See Shell.\n")
|
||||||
@@ -3325,7 +3322,7 @@ class FlatCAMExcEditor(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() == True:
|
||||||
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])
|
||||||
|
|
||||||
@@ -3560,14 +3557,14 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||||||
for storage in self.storage_dict:
|
for storage in self.storage_dict:
|
||||||
for obj in self.storage_dict[storage].get_objects():
|
for obj in self.storage_dict[storage].get_objects():
|
||||||
if (sel_type is True and poly_selection.contains(obj.geo)) or \
|
if (sel_type is True and poly_selection.contains(obj.geo)) or \
|
||||||
(sel_type is False and poly_selection.intersects(obj.geo)):
|
(sel_type is False and poly_selection.intersects(obj.geo)):
|
||||||
|
|
||||||
if obj in self.selected:
|
if obj in self.selected:
|
||||||
# remove the shape object from the selected shapes storage
|
# remove the shape object from the selected shapes storage
|
||||||
self.selected.remove(obj)
|
self.selected.remove(obj)
|
||||||
else:
|
else:
|
||||||
# add the shape object to the selected shapes storage
|
# add the shape object to the selected shapes storage
|
||||||
self.selected.append(obj)
|
self.selected.append(obj)
|
||||||
else:
|
else:
|
||||||
# clear the selection shapes storage
|
# clear the selection shapes storage
|
||||||
self.selected = []
|
self.selected = []
|
||||||
@@ -3883,7 +3880,8 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||||||
# self.points_edit it's only useful first time when we load the data into the storage
|
# self.points_edit it's only useful first time when we load the data into the storage
|
||||||
# but is still used as referecen when building tool_table in self.build_ui()
|
# but is still used as referecen when building tool_table in self.build_ui()
|
||||||
# the number of drills displayed in column 2 is just a len(self.points_edit) therefore
|
# the number of drills displayed in column 2 is just a len(self.points_edit) therefore
|
||||||
# deleting self.points_edit elements (doesn't matter who but just the number) solved the display issue.
|
# deleting self.points_edit elements (doesn't matter who but just the number)
|
||||||
|
# solved the display issue.
|
||||||
del self.points_edit[storage][0]
|
del self.points_edit[storage][0]
|
||||||
else:
|
else:
|
||||||
self.storage_dict[storage].remove(del_shape)
|
self.storage_dict[storage].remove(del_shape)
|
||||||
|
|||||||
@@ -2222,7 +2222,7 @@ class FCRectangle(FCShapeTool):
|
|||||||
self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero.png'))
|
self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero.png'))
|
||||||
QtGui.QGuiApplication.setOverrideCursor(self.cursor)
|
QtGui.QGuiApplication.setOverrideCursor(self.cursor)
|
||||||
|
|
||||||
self.draw_app.app.inform.emit( _("Click on 1st corner ..."))
|
self.draw_app.app.inform.emit(_("Click on 1st corner ..."))
|
||||||
|
|
||||||
def click(self, point):
|
def click(self, point):
|
||||||
self.points.append(point)
|
self.points.append(point)
|
||||||
@@ -2699,7 +2699,6 @@ class FCText(FCShapeTool):
|
|||||||
self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_text.png'))
|
self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_text.png'))
|
||||||
QtGui.QGuiApplication.setOverrideCursor(self.cursor)
|
QtGui.QGuiApplication.setOverrideCursor(self.cursor)
|
||||||
|
|
||||||
|
|
||||||
# self.shape_buffer = self.draw_app.shape_buffer
|
# self.shape_buffer = self.draw_app.shape_buffer
|
||||||
self.draw_app = draw_app
|
self.draw_app = draw_app
|
||||||
self.app = draw_app.app
|
self.app = draw_app.app
|
||||||
@@ -2722,21 +2721,19 @@ class FCText(FCShapeTool):
|
|||||||
log.debug("Font geometry is empty or incorrect: %s" % str(e))
|
log.debug("Font geometry is empty or incorrect: %s" % str(e))
|
||||||
self.draw_app.app.inform.emit('[ERROR] %s: %s' %
|
self.draw_app.app.inform.emit('[ERROR] %s: %s' %
|
||||||
(_("Font not supported. Only Regular, Bold, Italic and BoldItalic are "
|
(_("Font not supported. Only Regular, Bold, Italic and BoldItalic are "
|
||||||
"supported. Error"), str(e)))
|
"supported. Error"), str(e)))
|
||||||
self.text_gui.text_path = []
|
self.text_gui.text_path = []
|
||||||
self.text_gui.hide_tool()
|
self.text_gui.hide_tool()
|
||||||
self.draw_app.select_tool('select')
|
self.draw_app.select_tool('select')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
|
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' % _("No text to add."))
|
||||||
_("No text to add."))
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self.text_gui.text_path = []
|
self.text_gui.text_path = []
|
||||||
self.text_gui.hide_tool()
|
self.text_gui.hide_tool()
|
||||||
self.complete = True
|
self.complete = True
|
||||||
self.draw_app.app.inform.emit('[success]%s' %
|
self.draw_app.app.inform.emit('[success]%s' % _(" Done. Adding Text completed."))
|
||||||
_(" Done. Adding Text completed."))
|
|
||||||
|
|
||||||
def utility_geometry(self, data=None):
|
def utility_geometry(self, data=None):
|
||||||
"""
|
"""
|
||||||
@@ -3054,7 +3051,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
"text": {"button": self.app.ui.geo_add_text_btn,
|
"text": {"button": self.app.ui.geo_add_text_btn,
|
||||||
"constructor": FCText},
|
"constructor": FCText},
|
||||||
"buffer": {"button": self.app.ui.geo_add_buffer_btn,
|
"buffer": {"button": self.app.ui.geo_add_buffer_btn,
|
||||||
"constructor": FCBuffer},
|
"constructor": FCBuffer},
|
||||||
"paint": {"button": self.app.ui.geo_add_paint_btn,
|
"paint": {"button": self.app.ui.geo_add_paint_btn,
|
||||||
"constructor": FCPaint},
|
"constructor": FCPaint},
|
||||||
"eraser": {"button": self.app.ui.geo_eraser_btn,
|
"eraser": {"button": self.app.ui.geo_eraser_btn,
|
||||||
@@ -3062,11 +3059,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
"move": {"button": self.app.ui.geo_move_btn,
|
"move": {"button": self.app.ui.geo_move_btn,
|
||||||
"constructor": FCMove},
|
"constructor": FCMove},
|
||||||
"transform": {"button": self.app.ui.geo_transform_btn,
|
"transform": {"button": self.app.ui.geo_transform_btn,
|
||||||
"constructor": FCTransform},
|
"constructor": FCTransform},
|
||||||
"copy": {"button": self.app.ui.geo_copy_btn,
|
"copy": {"button": self.app.ui.geo_copy_btn,
|
||||||
"constructor": FCCopy},
|
"constructor": FCCopy},
|
||||||
"explode": {"button": self.app.ui.geo_explode_btn,
|
"explode": {"button": self.app.ui.geo_explode_btn,
|
||||||
"constructor": FCExplode}
|
"constructor": FCExplode}
|
||||||
}
|
}
|
||||||
|
|
||||||
# # ## Data
|
# # ## Data
|
||||||
@@ -3496,7 +3493,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
except (TypeError, AttributeError):
|
except (TypeError, AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.app.ui.draw_text.triggered.disconnect()
|
self.app.ui.draw_text.triggered.disconnect()
|
||||||
except (TypeError, AttributeError):
|
except (TypeError, AttributeError):
|
||||||
@@ -3555,12 +3551,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
self.add_shape(subshape)
|
self.add_shape(subshape)
|
||||||
return
|
return
|
||||||
|
|
||||||
assert isinstance(shape, DrawToolShape), \
|
assert isinstance(shape, DrawToolShape), "Expected a DrawToolShape, got %s" % type(shape)
|
||||||
"Expected a DrawToolShape, got %s" % type(shape)
|
assert shape.geo is not None, "Shape object has empty geometry (None)"
|
||||||
|
|
||||||
assert shape.geo is not None, \
|
|
||||||
"Shape object has empty geometry (None)"
|
|
||||||
|
|
||||||
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or \
|
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or \
|
||||||
not isinstance(shape.geo, list), "Shape objects has empty geometry ([])"
|
not isinstance(shape.geo, list), "Shape objects has empty geometry ([])"
|
||||||
|
|
||||||
@@ -4116,13 +4108,17 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if shape in self.selected:
|
if shape in self.selected:
|
||||||
self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_sel_draw_color'] + 'FF', linewidth=2)
|
self.plot_shape(geometry=shape.geo,
|
||||||
|
color=self.app.defaults['global_sel_draw_color'] + 'FF',
|
||||||
|
linewidth=2)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_draw_color'] + "FF")
|
self.plot_shape(geometry=shape.geo,
|
||||||
|
color=self.app.defaults['global_draw_color'] + "FF")
|
||||||
|
|
||||||
for shape in self.utility:
|
for shape in self.utility:
|
||||||
self.plot_shape(geometry=shape.geo, linewidth=1)
|
self.plot_shape(geometry=shape.geo,
|
||||||
|
linewidth=1)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.shapes.redraw()
|
self.shapes.redraw()
|
||||||
@@ -4482,7 +4478,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
results = []
|
results = []
|
||||||
for t in selected:
|
for t in selected:
|
||||||
if isinstance(t.geo, Polygon) and not t.geo.is_empty:
|
if isinstance(t.geo, Polygon) and not t.geo.is_empty:
|
||||||
results.append((t.geo.exterior).buffer(
|
results.append(t.geo.exterior.buffer(
|
||||||
buf_distance - 1e-10,
|
buf_distance - 1e-10,
|
||||||
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
|
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
|
||||||
join_style=join_style)
|
join_style=join_style)
|
||||||
@@ -4513,22 +4509,18 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
selected = self.get_selected()
|
selected = self.get_selected()
|
||||||
|
|
||||||
if buf_distance < 0:
|
if buf_distance < 0:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Negative buffer value is not accepted."))
|
||||||
_("Negative buffer value is not accepted.")
|
|
||||||
)
|
|
||||||
# deselect everything
|
# deselect everything
|
||||||
self.selected = []
|
self.selected = []
|
||||||
self.replot()
|
self.replot()
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
if len(selected) == 0:
|
if len(selected) == 0:
|
||||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected for buffering."))
|
||||||
_("Nothing selected for buffering."))
|
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
if not isinstance(buf_distance, float):
|
if not isinstance(buf_distance, float):
|
||||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Invalid distance for buffering."))
|
||||||
_("Invalid distance for buffering."))
|
|
||||||
# deselect everything
|
# deselect everything
|
||||||
self.selected = []
|
self.selected = []
|
||||||
self.replot()
|
self.replot()
|
||||||
@@ -4540,7 +4532,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
t.geo = Polygon(t.geo)
|
t.geo = Polygon(t.geo)
|
||||||
|
|
||||||
if isinstance(t.geo, Polygon) and not t.geo.is_empty:
|
if isinstance(t.geo, Polygon) and not t.geo.is_empty:
|
||||||
results.append((t.geo).buffer(
|
results.append(t.geo.buffer(
|
||||||
-buf_distance + 1e-10,
|
-buf_distance + 1e-10,
|
||||||
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
|
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
|
||||||
join_style=join_style)
|
join_style=join_style)
|
||||||
@@ -4558,8 +4550,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
self.add_shape(DrawToolShape(sha))
|
self.add_shape(DrawToolShape(sha))
|
||||||
|
|
||||||
self.replot()
|
self.replot()
|
||||||
self.app.inform.emit('[success] %s' %
|
self.app.inform.emit('[success] %s' % _("Interior buffer geometry created."))
|
||||||
_("Interior buffer geometry created."))
|
|
||||||
|
|
||||||
def buffer_ext(self, buf_distance, join_style):
|
def buffer_ext(self, buf_distance, join_style):
|
||||||
selected = self.get_selected()
|
selected = self.get_selected()
|
||||||
@@ -4592,7 +4583,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
t.geo = Polygon(t.geo)
|
t.geo = Polygon(t.geo)
|
||||||
|
|
||||||
if isinstance(t.geo, Polygon) and not t.geo.is_empty:
|
if isinstance(t.geo, Polygon) and not t.geo.is_empty:
|
||||||
results.append((t.geo).buffer(
|
results.append(t.geo.buffer(
|
||||||
buf_distance,
|
buf_distance,
|
||||||
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
|
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
|
||||||
join_style=join_style)
|
join_style=join_style)
|
||||||
@@ -4610,68 +4601,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
self.add_shape(DrawToolShape(sha))
|
self.add_shape(DrawToolShape(sha))
|
||||||
|
|
||||||
self.replot()
|
self.replot()
|
||||||
self.app.inform.emit('[success] %s' %
|
self.app.inform.emit('[success] %s' % _("Exterior buffer geometry created."))
|
||||||
_("Exterior buffer geometry created."))
|
|
||||||
|
|
||||||
# def paint(self, tooldia, overlap, margin, method):
|
|
||||||
# selected = self.get_selected()
|
|
||||||
#
|
|
||||||
# if len(selected) == 0:
|
|
||||||
# self.app.inform.emit("[WARNING] Nothing selected for painting.")
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# for param in [tooldia, overlap, margin]:
|
|
||||||
# if not isinstance(param, float):
|
|
||||||
# param_name = [k for k, v in locals().items() if v is param][0]
|
|
||||||
# self.app.inform.emit("[WARNING] Invalid value for {}".format(param))
|
|
||||||
#
|
|
||||||
# # Todo: Check for valid method.
|
|
||||||
#
|
|
||||||
# # Todo: This is the 3rd implementation on painting polys... try to consolidate
|
|
||||||
#
|
|
||||||
# results = []
|
|
||||||
#
|
|
||||||
# def recurse(geo):
|
|
||||||
# try:
|
|
||||||
# for subg in geo:
|
|
||||||
# for subsubg in recurse(subg):
|
|
||||||
# yield subsubg
|
|
||||||
# except TypeError:
|
|
||||||
# if isinstance(geo, LinearRing):
|
|
||||||
# yield geo
|
|
||||||
#
|
|
||||||
# raise StopIteration
|
|
||||||
#
|
|
||||||
# for geo in selected:
|
|
||||||
# print(type(geo.geo))
|
|
||||||
#
|
|
||||||
# local_results = []
|
|
||||||
# for poly in recurse(geo.geo):
|
|
||||||
# if method == "seed":
|
|
||||||
# # Type(cp) == FlatCAMRTreeStorage | None
|
|
||||||
# cp = Geometry.clear_polygon2(poly.buffer(-margin),
|
|
||||||
# tooldia, overlap=overlap)
|
|
||||||
#
|
|
||||||
# else:
|
|
||||||
# # Type(cp) == FlatCAMRTreeStorage | None
|
|
||||||
# cp = Geometry.clear_polygon(poly.buffer(-margin),
|
|
||||||
# tooldia, overlap=overlap)
|
|
||||||
#
|
|
||||||
# if cp is not None:
|
|
||||||
# local_results += list(cp.get_objects())
|
|
||||||
#
|
|
||||||
# results.append(cascaded_union(local_results))
|
|
||||||
#
|
|
||||||
# # This is a dirty patch:
|
|
||||||
# for r in results:
|
|
||||||
# self.add_shape(DrawToolShape(r))
|
|
||||||
#
|
|
||||||
# self.replot()
|
|
||||||
|
|
||||||
def paint(self, tooldia, overlap, margin, connect, contour, method):
|
def paint(self, tooldia, overlap, margin, connect, contour, method):
|
||||||
|
|
||||||
self.paint_tooldia = tooldia
|
self.paint_tooldia = tooldia
|
||||||
|
|
||||||
selected = self.get_selected()
|
selected = self.get_selected()
|
||||||
|
|
||||||
if len(selected) == 0:
|
if len(selected) == 0:
|
||||||
|
|||||||
Reference in New Issue
Block a user