- moved all the new_object related methods in their own class AppObjects.AppObject

This commit is contained in:
Marius Stanciu 2020-05-18 17:31:02 +03:00 committed by Marius
parent 710a84b442
commit 2bcdeff7ef
55 changed files with 579 additions and 554 deletions

View File

@ -2239,7 +2239,7 @@ class FlatCAMExcEditor(QtCore.QObject):
# store the status of the editor so the Delete at object level will not work until the edit is finished
self.editor_active = False
log.debug("Initialization of the FlatCAM Excellon Editor is finished ...")
log.debug("Initialization of the Excellon Editor is finished ...")
def pool_recreated(self, pool):
self.shapes.pool = pool
@ -3336,7 +3336,7 @@ class FlatCAMExcEditor(QtCore.QObject):
with self.app.proc_container.new(_("Creating Excellon.")):
try:
edited_obj = self.app.new_object("excellon", outname, obj_init)
edited_obj = self.app.app_obj.new_object("excellon", outname, obj_init)
edited_obj.source_file = self.app.export_excellon(obj_name=edited_obj.options['name'],
local_use=edited_obj,
filename=None,

View File

@ -3552,7 +3552,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
# store the status of the editor so the Delete at object level will not work until the edit is finished
self.editor_active = False
log.debug("Initialization of the FlatCAM Geometry Editor is finished ...")
log.debug("Initialization of the Geometry Editor is finished ...")
def pool_recreated(self, pool):
self.shapes.pool = pool

View File

@ -3110,7 +3110,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.complete = True
self.set_ui()
log.debug("Initialization of the FlatCAM Gerber Editor is finished ...")
log.debug("Initialization of the Gerber Editor is finished ...")
def pool_recreated(self, pool):
self.shapes.pool = pool
@ -4346,7 +4346,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
with self.app.proc_container.new(_("Creating Gerber.")):
try:
self.app.new_object("gerber", outname, obj_init)
self.app.app_obj.new_object("gerber", outname, obj_init)
except Exception as e:
log.error("Error on Edited object creation: %s" % str(e))
# make sure to clean the previous results

View File

@ -2477,7 +2477,7 @@ class MainGUI(QtWidgets.QMainWindow):
# New Geometry
if key == QtCore.Qt.Key_B:
self.app.new_gerber_object()
self.app.app_obj.new_gerber_object()
# New Geometry
if key == QtCore.Qt.Key_D:
@ -2497,7 +2497,7 @@ class MainGUI(QtWidgets.QMainWindow):
# New Excellon
if key == QtCore.Qt.Key_L:
self.app.new_excellon_object()
self.app.app_obj.new_excellon_object()
# Move tool toggle
if key == QtCore.Qt.Key_M:
@ -2505,7 +2505,7 @@ class MainGUI(QtWidgets.QMainWindow):
# New Geometry
if key == QtCore.Qt.Key_N:
self.app.new_geometry_object()
self.app.app_obj.new_geometry_object()
# Set Origin
if key == QtCore.Qt.Key_O:

View File

@ -48,9 +48,9 @@ class CanvasCache(QtCore.QObject):
Case story #1:
1) No objects in the project.
2) Object is created (new_object() emits object_created(obj)).
2) Object is created (app_obj.new_object() emits object_created(obj)).
on_object_created() adds (i) object to collection and emits
(ii) new_object_available() then calls (iii) object.plot()
(ii) app_obj.new_object_available() then calls (iii) object.plot()
3) object.plot() creates axes if necessary on
app.collection.figure. Then plots on it.
4) Plots on a cache-size canvas (in background).
@ -116,7 +116,7 @@ class CanvasCache(QtCore.QObject):
# Continue to update the cache.
# def on_new_object_available(self):
# def on_app_obj.new_object_available(self):
#
# log.debug("A new object is available. Should plot it!")

View File

@ -43,7 +43,7 @@ class PreferencesUIManager:
self.preferences_changed_flag = False
# when adding entries here read the comments in the method found below named:
# def new_object(self, kind, name, initialize, active=True, fit=True, plot=True)
# def app_obj.new_object(self, kind, name, initialize, active=True, fit=True, plot=True)
self.defaults_form_fields = {
# General App
"decimals_inch": self.ui.general_defaults_form.general_app_group.precision_inch_entry,

View File

@ -4,6 +4,7 @@
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
# Modified by Marius Stanciu (2019) #
# ###########################################################
import urllib.request
@ -55,12 +56,7 @@ from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
from AppGUI.preferences.PreferencesUIManager import PreferencesUIManager
from AppObjects.ObjectCollection import *
from AppObjects.FlatCAMObj import FlatCAMObj
from AppObjects.FlatCAMCNCJob import CNCJobObject
from AppObjects.FlatCAMDocument import DocumentObject
from AppObjects.FlatCAMExcellon import ExcellonObject
from AppObjects.FlatCAMGeometry import GeometryObject
from AppObjects.FlatCAMGerber import GerberObject
from AppObjects.FlatCAMScript import ScriptObject
from AppObjects.AppObject import AppObject
# FlatCAM Parsing files
from AppParsers.ParseExcellon import Excellon
@ -226,20 +222,6 @@ class App(QtCore.QObject):
# Percentage of progress
progress = QtCore.pyqtSignal(int)
plots_updated = QtCore.pyqtSignal()
# Emitted by new_object() and passes the new object as argument, plot flag.
# on_object_created() adds the object to the collection, plots on appropriate flag
# and emits new_object_available.
object_created = QtCore.pyqtSignal(object, bool, bool)
# Emitted when a object has been changed (like scaled, mirrored)
object_changed = QtCore.pyqtSignal(object)
# Emitted after object has been plotted.
# Calls 'on_zoom_fit' method to fit object in scene view in main thread to prevent drawing glitches.
object_plotted = QtCore.pyqtSignal(object)
# Emitted when a new object has been added or deleted from/to the collection
object_status_changed = QtCore.pyqtSignal(object, str, str)
@ -674,9 +656,11 @@ class App(QtCore.QObject):
# #################################### SETUP OBJECT COLLECTION ##############################################
# ###########################################################################################################
self.collection = ObjectCollection(self)
self.collection = ObjectCollection(app=self)
self.ui.project_tab_layout.addWidget(self.collection.view)
self.app_obj = AppObject(app=self)
# ### Adjust tabs width ## ##
# self.collection.view.setMinimumWidth(self.ui.options_scroll_area.widget().sizeHint().width() +
# self.ui.options_scroll_area.verticalScrollBar().sizeHint().width())
@ -779,12 +763,6 @@ class App(QtCore.QObject):
self.message.connect(lambda: message_dialog(parent=self.ui))
# self.progress.connect(self.set_progress_bar)
# signals that are emitted when object state changes
self.object_created.connect(self.on_object_created)
self.object_changed.connect(self.on_object_changed)
self.object_plotted.connect(self.on_object_plotted)
self.plots_updated.connect(self.on_plots_updated)
# signals emitted when file state change
self.file_opened.connect(self.register_recent)
self.file_opened.connect(lambda kind, filename: self.register_folder(filename))
@ -793,10 +771,10 @@ class App(QtCore.QObject):
# ########################################## Standard signals ###############################################
# ### Menu
self.ui.menufilenewproject.triggered.connect(self.on_file_new_click)
self.ui.menufilenewgeo.triggered.connect(self.new_geometry_object)
self.ui.menufilenewgrb.triggered.connect(self.new_gerber_object)
self.ui.menufilenewexc.triggered.connect(self.new_excellon_object)
self.ui.menufilenewdoc.triggered.connect(self.new_document_object)
self.ui.menufilenewgeo.triggered.connect(self.app_obj.new_geometry_object)
self.ui.menufilenewgrb.triggered.connect(self.app_obj.new_gerber_object)
self.ui.menufilenewexc.triggered.connect(self.app_obj.new_excellon_object)
self.ui.menufilenewdoc.triggered.connect(self.app_obj.new_document_object)
self.ui.menufileopengerber.triggered.connect(self.on_fileopengerber)
self.ui.menufileopenexcellon.triggered.connect(self.on_fileopenexcellon)
@ -935,9 +913,9 @@ class App(QtCore.QObject):
self.ui.popmenu_disable.triggered.connect(lambda: self.toggle_plots(self.collection.get_selected()))
self.ui.popmenu_panel_toggle.triggered.connect(self.ui.on_toggle_notebook)
self.ui.popmenu_new_geo.triggered.connect(self.new_geometry_object)
self.ui.popmenu_new_grb.triggered.connect(self.new_gerber_object)
self.ui.popmenu_new_exc.triggered.connect(self.new_excellon_object)
self.ui.popmenu_new_geo.triggered.connect(self.app_obj.new_geometry_object)
self.ui.popmenu_new_grb.triggered.connect(self.app_obj.new_gerber_object)
self.ui.popmenu_new_exc.triggered.connect(self.app_obj.new_excellon_object)
self.ui.popmenu_new_prj.triggered.connect(self.on_file_new)
self.ui.zoomfit.triggered.connect(self.on_zoom_fit)
@ -1918,7 +1896,7 @@ class App(QtCore.QObject):
self.calculator_tool = ToolCalculator(self)
self.calculator_tool.install(icon=QtGui.QIcon(self.resource_location + '/calculator16.png'), separator=True)
self.sub_tool = ToolSub(self)
self.sub_tool = ToolSub(app=self)
self.sub_tool.install(icon=QtGui.QIcon(self.resource_location + '/sub32.png'),
pos=self.ui.menutool, separator=True)
@ -2071,9 +2049,9 @@ class App(QtCore.QObject):
self.ui.zoom_out_btn.triggered.connect(lambda: self.plotcanvas.zoom(1.5))
# Edit Toolbar Signals
self.ui.newgeo_btn.triggered.connect(self.new_geometry_object)
self.ui.newgrb_btn.triggered.connect(self.new_gerber_object)
self.ui.newexc_btn.triggered.connect(self.new_excellon_object)
self.ui.newgeo_btn.triggered.connect(self.app_obj.new_geometry_object)
self.ui.newgrb_btn.triggered.connect(self.app_obj.new_gerber_object)
self.ui.newexc_btn.triggered.connect(self.app_obj.new_excellon_object)
self.ui.editgeo_btn.triggered.connect(self.object2editor)
self.ui.update_obj_btn.triggered.connect(lambda: self.editor2object())
self.ui.copy_btn.triggered.connect(self.on_copy_command)
@ -2665,347 +2643,6 @@ class App(QtCore.QObject):
# Re-build the recent items menu
self.setup_recent_items()
def new_object(self, kind, name, initialize, plot=True, autoselected=True):
"""
Creates a new specialized FlatCAMObj and attaches it to the application,
this is, updates the GUI accordingly, any other records and plots it.
This method is thread-safe.
Notes:
* If the name is in use, the self.collection will modify it
when appending it to the collection. There is no need to handle
name conflicts here.
:param kind: The kind of object to create. One of 'gerber', 'excellon', 'cncjob' and 'geometry'.
:type kind: str
:param name: Name for the object.
:type name: str
:param initialize: Function to run after creation of the object but before it is attached to the application.
The function is called with 2 parameters: the new object and the App instance.
:type initialize: function
:param plot: If to plot the resulting object
:param autoselected: if the resulting object is autoselected in the Project tab and therefore in the
self.collection
:return: None
:rtype: None
"""
App.log.debug("new_object()")
obj_plot = plot
obj_autoselected = autoselected
t0 = time.time() # Debug
# ## Create object
classdict = {
"gerber": GerberObject,
"excellon": ExcellonObject,
"cncjob": CNCJobObject,
"geometry": GeometryObject,
"script": ScriptObject,
"document": DocumentObject
}
App.log.debug("Calling object constructor...")
# Object creation/instantiation
obj = classdict[kind](name)
obj.units = self.options["units"]
# IMPORTANT
# The key names in defaults and options dictionary's are not random:
# they have to have in name first the type of the object (geometry, excellon, cncjob and gerber) or how it's
# called here, the 'kind' followed by an underline. Above the App default values from self.defaults are
# copied to self.options. After that, below, depending on the type of
# object that is created, it will strip the name of the object and the underline (if the original key was
# let's say "excellon_toolchange", it will strip the excellon_) and to the obj.options the key will become
# "toolchange"
for option in self.options:
if option.find(kind + "_") == 0:
oname = option[len(kind) + 1:]
obj.options[oname] = self.options[option]
obj.isHovering = False
obj.notHovering = True
# Initialize as per user request
# User must take care to implement initialize
# in a thread-safe way as is is likely that we
# have been invoked in a separate thread.
t1 = time.time()
self.log.debug("%f seconds before initialize()." % (t1 - t0))
try:
return_value = initialize(obj, self)
except Exception as e:
msg = '[ERROR_NOTCL] %s' % _("An internal error has occurred. See shell.\n")
msg += _("Object ({kind}) failed because: {error} \n\n").format(kind=kind, error=str(e))
msg += traceback.format_exc()
self.inform.emit(msg)
return "fail"
t2 = time.time()
self.log.debug("%f seconds executing initialize()." % (t2 - t1))
if return_value == 'fail':
log.debug("Object (%s) parsing and/or geometry creation failed." % kind)
return "fail"
# Check units and convert if necessary
# This condition CAN be true because initialize() can change obj.units
if self.options["units"].upper() != obj.units.upper():
self.inform.emit('%s: %s' % (_("Converting units to "), self.options["units"]))
obj.convert_units(self.options["units"])
t3 = time.time()
self.log.debug("%f seconds converting units." % (t3 - t2))
# Create the bounding box for the object and then add the results to the obj.options
# But not for Scripts or for Documents
if kind != 'document' and kind != 'script':
try:
xmin, ymin, xmax, ymax = obj.bounds()
obj.options['xmin'] = xmin
obj.options['ymin'] = ymin
obj.options['xmax'] = xmax
obj.options['ymax'] = ymax
except Exception as e:
log.warning("App.new_object() -> The object has no bounds properties. %s" % str(e))
return "fail"
try:
if kind == 'excellon':
obj.fill_color = self.defaults["excellon_plot_fill"]
obj.outline_color = self.defaults["excellon_plot_line"]
if kind == 'gerber':
obj.fill_color = self.defaults["gerber_plot_fill"]
obj.outline_color = self.defaults["gerber_plot_line"]
except Exception as e:
log.warning("App.new_object() -> setting colors error. %s" % str(e))
# update the KeyWords list with the name of the file
self.myKeywords.append(obj.options['name'])
log.debug("Moving new object back to main thread.")
# Move the object to the main thread and let the app know that it is available.
obj.moveToThread(self.main_thread)
self.object_created.emit(obj, obj_plot, obj_autoselected)
return obj
def new_excellon_object(self):
"""
Creates a new, blank Excellon object.
:return: None
"""
self.defaults.report_usage("new_excellon_object()")
self.new_object('excellon', 'new_exc', lambda x, y: None, plot=False)
def new_geometry_object(self):
"""
Creates a new, blank and single-tool Geometry object.
:return: None
"""
self.defaults.report_usage("new_geometry_object()")
def initialize(obj, app):
obj.multitool = False
self.new_object('geometry', 'new_geo', initialize, plot=False)
def new_gerber_object(self):
"""
Creates a new, blank Gerber object.
:return: None
"""
self.defaults.report_usage("new_gerber_object()")
def initialize(grb_obj, app):
grb_obj.multitool = False
grb_obj.source_file = []
grb_obj.multigeo = False
grb_obj.follow = False
grb_obj.apertures = {}
grb_obj.solid_geometry = []
try:
grb_obj.options['xmin'] = 0
grb_obj.options['ymin'] = 0
grb_obj.options['xmax'] = 0
grb_obj.options['ymax'] = 0
except KeyError:
pass
self.new_object('gerber', 'new_grb', initialize, plot=False)
def new_script_object(self):
"""
Creates a new, blank TCL Script object.
:return: None
"""
self.defaults.report_usage("new_script_object()")
# commands_list = "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, " \
# "AlignDrillGrid, Bbox, Bounds, ClearShell, CopperClear,\n" \
# "# Cncjob, Cutout, Delete, Drillcncjob, ExportDXF, ExportExcellon, ExportGcode,\n" \
# "# ExportGerber, ExportSVG, Exteriors, Follow, GeoCutout, GeoUnion, GetNames,\n" \
# "# GetSys, ImportSvg, Interiors, Isolate, JoinExcellon, JoinGeometry, " \
# "ListSys, MillDrills,\n" \
# "# MillSlots, Mirror, New, NewExcellon, NewGeometry, NewGerber, Nregions, " \
# "Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n" \
# "# Options, Paint, Panelize, PlotAl, PlotObjects, SaveProject, " \
# "SaveSys, Scale, SetActive, SetSys, SetOrigin, Skew, SubtractPoly,\n" \
# "# SubtractRectangle, Version, WriteGCode\n"
new_source_file = '# %s\n' % _('CREATE A NEW FLATCAM TCL SCRIPT') + \
'# %s:\n' % _('TCL Tutorial is here') + \
'# https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n' + '\n\n' + \
'# %s:\n' % _("FlatCAM commands list")
new_source_file += '# %s\n\n' % _("Type >help< followed by Run Code for a list of FlatCAM Tcl Commands "
"(displayed in Tcl Shell).")
def initialize(obj, app):
obj.source_file = deepcopy(new_source_file)
outname = 'new_script'
self.new_object('script', outname, initialize, plot=False)
def new_document_object(self):
"""
Creates a new, blank Document object.
:return: None
"""
self.defaults.report_usage("new_document_object()")
def initialize(obj, app):
obj.source_file = ""
self.new_object('document', 'new_document', initialize, plot=False)
def on_object_created(self, obj, plot, auto_select):
"""
Event callback for object creation.
It will add the new object to the collection. After that it will plot the object in a threaded way
:param obj: The newly created FlatCAM object.
:param plot: if the newly create object t obe plotted
:param auto_select: if the newly created object to be autoselected after creation
:return: None
"""
t0 = time.time() # DEBUG
self.log.debug("on_object_created()")
# The Collection might change the name if there is a collision
self.collection.append(obj)
# after adding the object to the collection always update the list of objects that are in the collection
self.all_objects_list = self.collection.get_list()
# self.inform.emit('[selected] %s created & selected: %s' %
# (str(obj.kind).capitalize(), str(obj.options['name'])))
if obj.kind == 'gerber':
self.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='green',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'excellon':
self.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='brown',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'cncjob':
self.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='blue',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'geometry':
self.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='red',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'script':
self.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='orange',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'document':
self.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='darkCyan',
name=str(obj.options['name']), tx=_("created/selected"))
)
# update the SHELL auto-completer model with the name of the new object
self.shell._edit.set_model_data(self.myKeywords)
if auto_select:
# select the just opened object but deselect the previous ones
self.collection.set_all_inactive()
self.collection.set_active(obj.options["name"])
else:
self.collection.set_all_inactive()
# here it is done the object plotting
def worker_task(t_obj):
with self.proc_container.new(_("Plotting")):
if isinstance(t_obj, CNCJobObject):
t_obj.plot(kind=self.defaults["cncjob_plot_kind"])
else:
t_obj.plot()
t1 = time.time() # DEBUG
self.log.debug("%f seconds adding object and plotting." % (t1 - t0))
self.object_plotted.emit(t_obj)
# Send to worker
# self.worker.add_task(worker_task, [self])
if plot is True:
self.worker_task.emit({'fcn': worker_task, 'params': [obj]})
def on_object_changed(self, obj):
"""
Called whenever the geometry of the object was changed in some way.
This require the update of it's bounding values so it can be the selected on canvas.
Update the bounding box data from obj.options
:param obj: the object that was changed
:return: None
"""
try:
xmin, ymin, xmax, ymax = obj.bounds()
except TypeError:
return
obj.options['xmin'] = xmin
obj.options['ymin'] = ymin
obj.options['xmax'] = xmax
obj.options['ymax'] = ymax
log.debug("Object changed, updating the bounding box data on self.options")
# delete the old selection shape
self.delete_selection_shape()
self.should_we_save = True
def on_object_plotted(self):
"""
Callback called whenever the plotted object needs to be fit into the viewport (canvas)
:return: None
"""
self.on_zoom_fit(None)
def on_about(self):
"""
Displays the "about" dialog found in the Menu --> Help.
@ -3976,7 +3613,7 @@ class App(QtCore.QObject):
for v in geo_obj.tools.values():
v['data']['name'] = obj_name_multi
self.new_object("geometry", obj_name_multi, initialize)
self.app_obj.new_object("geometry", obj_name_multi, initialize)
else:
def initialize(geo_obj, app):
GeometryObject.merge(geo_list=objs, geo_final=geo_obj, multigeo=False)
@ -3986,7 +3623,7 @@ class App(QtCore.QObject):
for v in geo_obj.tools.values():
v['data']['name'] = obj_name_single
self.new_object("geometry", obj_name_single, initialize)
self.app_obj.new_object("geometry", obj_name_single, initialize)
self.should_we_save = True
@ -4015,7 +3652,7 @@ class App(QtCore.QObject):
ExcellonObject.merge(exc_list=objs, exc_final=exc_obj, decimals=self.decimals)
app.inform.emit('[success] %s.' % _("Excellon merging finished"))
self.new_object("excellon", 'Combo_Excellon', initialize)
self.app_obj.new_object("excellon", 'Combo_Excellon', initialize)
self.should_we_save = True
def on_edit_join_grb(self):
@ -4043,7 +3680,7 @@ class App(QtCore.QObject):
GerberObject.merge(grb_list=objs, grb_final=grb_obj)
app.inform.emit('[success] %s.' % _("Gerber merging finished"))
self.new_object("gerber", 'Combo_Gerber', initialize)
self.app_obj.new_object("gerber", 'Combo_Gerber', initialize)
self.should_we_save = True
def on_convert_singlegeo_to_multigeo(self):
@ -4352,7 +3989,7 @@ class App(QtCore.QObject):
obj.convert_units(new_units)
# make that the properties stored in the object are also updated
self.object_changed.emit(obj)
self.app_obj.object_changed.emit(obj)
# rebuild the object UI
obj.build_ui()
@ -5017,7 +4654,7 @@ class App(QtCore.QObject):
for obj in obj_list:
obj.offset((x, y))
self.object_changed.emit(obj)
self.app_obj.object_changed.emit(obj)
# Update the object bounding box options
a, b, c, d = obj.bounds()
@ -5105,7 +4742,7 @@ class App(QtCore.QObject):
for obj in obj_list:
obj.offset((-x, -y))
self.object_changed.emit(obj)
self.app_obj.object_changed.emit(obj)
# Update the object bounding box options
a, b, c, d = obj.bounds()
@ -5468,15 +5105,15 @@ class App(QtCore.QObject):
try:
if isinstance(obj, ExcellonObject):
self.new_object("excellon", str(obj_name) + "_copy", initialize_excellon)
self.app_obj.new_object("excellon", str(obj_name) + "_copy", initialize_excellon)
elif isinstance(obj, GerberObject):
self.new_object("gerber", str(obj_name) + "_copy", initialize)
self.app_obj.new_object("gerber", str(obj_name) + "_copy", initialize)
elif isinstance(obj, GeometryObject):
self.new_object("geometry", str(obj_name) + "_copy", initialize)
self.app_obj.new_object("geometry", str(obj_name) + "_copy", initialize)
elif isinstance(obj, ScriptObject):
self.new_object("script", str(obj_name) + "_copy", initialize_script)
self.app_obj.new_object("script", str(obj_name) + "_copy", initialize_script)
elif isinstance(obj, DocumentObject):
self.new_object("document", str(obj_name) + "_copy", initialize_document)
self.app_obj.new_object("document", str(obj_name) + "_copy", initialize_document)
except Exception as e:
return "Operation failed: %s" % str(e)
@ -5517,11 +5154,11 @@ class App(QtCore.QObject):
obj_name = obj.options["name"]
try:
if isinstance(obj, ExcellonObject):
self.new_object("excellon", str(obj_name) + custom_name, initialize_excellon)
self.app_obj.new_object("excellon", str(obj_name) + custom_name, initialize_excellon)
elif isinstance(obj, GerberObject):
self.new_object("gerber", str(obj_name) + custom_name, initialize_gerber)
self.app_obj.new_object("gerber", str(obj_name) + custom_name, initialize_gerber)
elif isinstance(obj, GeometryObject):
self.new_object("geometry", str(obj_name) + custom_name, initialize_geometry)
self.app_obj.new_object("geometry", str(obj_name) + custom_name, initialize_geometry)
except Exception as er:
return "Operation failed: %s" % str(er)
@ -5588,9 +5225,9 @@ class App(QtCore.QObject):
try:
if isinstance(obj, ExcellonObject):
self.new_object("geometry", str(obj_name) + "_conv", initialize_excellon)
self.app_obj.new_object("geometry", str(obj_name) + "_conv", initialize_excellon)
else:
self.new_object("geometry", str(obj_name) + "_conv", initialize)
self.app_obj.new_object("geometry", str(obj_name) + "_conv", initialize)
except Exception as e:
return "Operation failed: %s" % str(e)
@ -5666,9 +5303,9 @@ class App(QtCore.QObject):
try:
if isinstance(obj, ExcellonObject):
self.new_object("gerber", str(obj_name) + "_conv", initialize_excellon)
self.app_obj.new_object("gerber", str(obj_name) + "_conv", initialize_excellon)
elif isinstance(obj, GeometryObject):
self.new_object("gerber", str(obj_name) + "_conv", initialize_geometry)
self.app_obj.new_object("gerber", str(obj_name) + "_conv", initialize_geometry)
else:
log.warning("App.convert_any2gerber --> This is no vaild object for conversion.")
@ -5960,7 +5597,7 @@ class App(QtCore.QObject):
for obj in obj_list:
obj.mirror('X', [px, py])
obj.plot()
self.object_changed.emit(obj)
self.app_obj.object_changed.emit(obj)
self.inform.emit('[success] %s' %
_("Flip on Y axis done."))
except Exception as e:
@ -6008,7 +5645,7 @@ class App(QtCore.QObject):
for obj in obj_list:
obj.mirror('Y', [px, py])
obj.plot()
self.object_changed.emit(obj)
self.app_obj.object_changed.emit(obj)
self.inform.emit('[success] %s' %
_("Flip on X axis done."))
except Exception as e:
@ -6064,7 +5701,7 @@ class App(QtCore.QObject):
for sel_obj in obj_list:
sel_obj.rotate(-float(num), point=(px, py))
sel_obj.plot()
self.object_changed.emit(sel_obj)
self.app_obj.object_changed.emit(sel_obj)
self.inform.emit('[success] %s' % _("Rotation done."))
except Exception as e:
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Rotation movement was not executed."), str(e)))
@ -6104,7 +5741,7 @@ class App(QtCore.QObject):
for obj in obj_list:
obj.skew(num, 0, point=(xminimal, yminimal))
obj.plot()
self.object_changed.emit(obj)
self.app_obj.object_changed.emit(obj)
self.inform.emit('[success] %s' % _("Skew on X axis done."))
def on_skewy(self):
@ -6141,7 +5778,7 @@ class App(QtCore.QObject):
for obj in obj_list:
obj.skew(0, num, point=(xminimal, yminimal))
obj.plot()
self.object_changed.emit(obj)
self.app_obj.object_changed.emit(obj)
self.inform.emit('[success] %s' % _("Skew on Y axis done."))
def on_plots_updated(self):
@ -7970,7 +7607,7 @@ class App(QtCore.QObject):
self.ui.position_label.setText("")
# self.ui.rel_position_label.setText("")
self.new_script_object()
self.app_obj.new_script_object()
# script_text = script_obj.source_file
#
@ -8891,7 +8528,7 @@ class App(QtCore.QObject):
# Object name
name = outname or filename.split('/')[-1].split('\\')[-1]
ret = self.new_object(obj_type, name, obj_init, autoselected=False, plot=plot)
ret = self.app_obj.new_object(obj_type, name, obj_init, autoselected=False, plot=plot)
if ret == 'fail':
self.inform.emit('[ERROR_NOTCL]%s' % _('Import failed.'))
@ -8937,7 +8574,7 @@ class App(QtCore.QObject):
# Object name
name = outname or filename.split('/')[-1].split('\\')[-1]
ret = self.new_object(obj_type, name, obj_init, autoselected=False, plot=plot)
ret = self.app_obj.new_object(obj_type, name, obj_init, autoselected=False, plot=plot)
if ret == 'fail':
self.inform.emit('[ERROR_NOTCL]%s' % _('Import failed.'))
@ -8998,11 +8635,11 @@ class App(QtCore.QObject):
name = outname or filename.split('/')[-1].split('\\')[-1]
# # ## Object creation # ##
ret_val = self.new_object("gerber", name, obj_init, autoselected=False, plot=plot)
ret_val = self.app_obj.new_object("gerber", name, obj_init, autoselected=False, plot=plot)
if ret_val == 'fail':
if from_tcl:
filename = self.defaults['global_tcl_path'] + '/' + name
ret_val = self.new_object("gerber", name, obj_init, autoselected=False, plot=plot)
ret_val = self.app_obj.new_object("gerber", name, obj_init, autoselected=False, plot=plot)
if ret_val == 'fail':
self.inform.emit('[ERROR_NOTCL]%s' % _('Open Gerber failed. Probable not a Gerber file.'))
return 'fail'
@ -9064,11 +8701,11 @@ class App(QtCore.QObject):
with self.proc_container.new(_("Opening Excellon.")):
# Object name
name = outname or filename.split('/')[-1].split('\\')[-1]
ret_val = self.new_object("excellon", name, obj_init, autoselected=False, plot=plot)
ret_val = self.app_obj.new_object("excellon", name, obj_init, autoselected=False, plot=plot)
if ret_val == 'fail':
if from_tcl:
filename = self.defaults['global_tcl_path'] + '/' + name
ret_val = self.new_object("excellon", name, obj_init, autoselected=False, plot=plot)
ret_val = self.app_obj.new_object("excellon", name, obj_init, autoselected=False, plot=plot)
if ret_val == 'fail':
self.inform.emit('[ERROR_NOTCL] %s' %
_('Open Excellon file failed. Probable not an Excellon file.'))
@ -9127,11 +8764,11 @@ class App(QtCore.QObject):
name = outname or filename.split('/')[-1].split('\\')[-1]
# New object creation and file processing
ret_val = self.new_object("cncjob", name, obj_init, autoselected=False, plot=plot)
ret_val = self.app_obj.new_object("cncjob", name, obj_init, autoselected=False, plot=plot)
if ret_val == 'fail':
if from_tcl:
filename = self.defaults['global_tcl_path'] + '/' + name
ret_val = self.new_object("cncjob", name, obj_init, autoselected=False, plot=plot)
ret_val = self.app_obj.new_object("cncjob", name, obj_init, autoselected=False, plot=plot)
if ret_val == 'fail':
self.inform.emit('[ERROR_NOTCL] %s' %
_("Failed to create CNCJob Object. Probable not a GCode file. "
@ -9200,7 +8837,7 @@ class App(QtCore.QObject):
name = outname or filename.split('/')[-1].split('\\')[-1]
# # ## Object creation # ##
ret = self.new_object("geometry", name, obj_init, autoselected=False)
ret = self.app_obj.new_object("geometry", name, obj_init, autoselected=False)
if ret == 'fail':
self.inform.emit('[ERROR_NOTCL]%s' % _(' Open HPGL2 failed. Probable not a HPGL2 file.'))
return 'fail'
@ -9254,10 +8891,10 @@ class App(QtCore.QObject):
script_name = outname or filename.split('/')[-1].split('\\')[-1]
# Object creation
ret_val = self.new_object("script", script_name, obj_init, autoselected=False, plot=False)
ret_val = self.app_obj.new_object("script", script_name, obj_init, autoselected=False, plot=False)
if ret_val == 'fail':
filename = self.defaults['global_tcl_path'] + '/' + script_name
ret_val = self.new_object("script", script_name, obj_init, autoselected=False, plot=False)
ret_val = self.app_obj.new_object("script", script_name, obj_init, autoselected=False, plot=False)
if ret_val == 'fail':
self.inform.emit('[ERROR_NOTCL]%s' % _('Failed to open TCL Script.'))
return 'fail'
@ -9320,7 +8957,7 @@ class App(QtCore.QObject):
2) Registers the file as recently opened.
3) Calls on_file_new()
4) Updates options
5) Calls new_object() with the object's from_dict() as init method.
5) Calls app_obj.new_object() with the object's from_dict() as init method.
6) Calls plot_all() if plot=True
:param filename: Name of the file from which to load.
@ -9422,7 +9059,7 @@ class App(QtCore.QObject):
)
)
self.new_object(obj['kind'], obj['options']['name'], obj_init, plot=plot)
self.app_obj.new_object(obj['kind'], obj['options']['name'], obj_init, plot=plot)
except Exception as e:
print('App.open_project() --> ' + str(e))
@ -9459,7 +9096,7 @@ class App(QtCore.QObject):
with self.proc_container.new("Plotting"):
obj.plot(kind=self.defaults["cncjob_plot_kind"])
if fit_view is True:
self.object_plotted.emit(obj)
self.app_obj.object_plotted.emit(obj)
if use_thread is True:
# Send to worker
@ -10044,8 +9681,6 @@ class App(QtCore.QObject):
self.worker_task.emit({'fcn': worker_task, 'params': [objects]})
# self.plots_updated.emit()
def disable_plots(self, objects):
"""
Disables plots
@ -10084,7 +9719,6 @@ class App(QtCore.QObject):
except Exception as e:
log.debug("App.disable_plots() --> %s" % str(e))
# self.plots_updated.emit()
def worker_task(objs):
with self.proc_container.new(_("Disabling plots ...")):
for plot_obj in objs:
@ -10115,7 +9749,7 @@ class App(QtCore.QObject):
obj.options['plot'] = True
else:
obj.options['plot'] = False
self.plots_updated.emit()
self.app_obj.plots_updated.emit()
def clear_plots(self):
"""

393
AppObjects/AppObject.py Normal file
View File

@ -0,0 +1,393 @@
# ###########################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
# Modified by Marius Stanciu (2020) #
# ###########################################################
from PyQt5 import QtCore
from AppObjects.ObjectCollection import *
from AppObjects.FlatCAMCNCJob import CNCJobObject
from AppObjects.FlatCAMDocument import DocumentObject
from AppObjects.FlatCAMExcellon import ExcellonObject
from AppObjects.FlatCAMGeometry import GeometryObject
from AppObjects.FlatCAMGerber import GerberObject
from AppObjects.FlatCAMScript import ScriptObject
import time
import traceback
# FlatCAM Translation
import gettext
import AppTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
class AppObject(QtCore.QObject):
# Emitted by app_obj.new_object() and passes the new object as argument, plot flag.
# on_object_created() adds the object to the collection, plots on appropriate flag
# and emits app_obj.new_object_available.
object_created = QtCore.pyqtSignal(object, bool, bool)
# Emitted when a object has been changed (like scaled, mirrored)
object_changed = QtCore.pyqtSignal(object)
# Emitted after object has been plotted.
# Calls 'on_zoom_fit' method to fit object in scene view in main thread to prevent drawing glitches.
object_plotted = QtCore.pyqtSignal(object)
plots_updated = QtCore.pyqtSignal()
def __init__(self, app):
super(AppObject, self).__init__()
self.app = app
# signals that are emitted when object state changes
self.object_created.connect(self.on_object_created)
self.object_changed.connect(self.on_object_changed)
self.object_plotted.connect(self.on_object_plotted)
self.plots_updated.connect(self.app.on_plots_updated)
def new_object(self, kind, name, initialize, plot=True, autoselected=True):
"""
Creates a new specialized FlatCAMObj and attaches it to the application,
this is, updates the GUI accordingly, any other records and plots it.
This method is thread-safe.
Notes:
* If the name is in use, the self.collection will modify it
when appending it to the collection. There is no need to handle
name conflicts here.
:param kind: The kind of object to create. One of 'gerber', 'excellon', 'cncjob' and 'geometry'.
:type kind: str
:param name: Name for the object.
:type name: str
:param initialize: Function to run after creation of the object but before it is attached to the application.
The function is called with 2 parameters: the new object and the App instance.
:type initialize: function
:param plot: If to plot the resulting object
:param autoselected: if the resulting object is autoselected in the Project tab and therefore in the
self.collection
:return: None
:rtype: None
"""
log.debug("AppObject.new_object()")
obj_plot = plot
obj_autoselected = autoselected
t0 = time.time() # Debug
# ## Create object
classdict = {
"gerber": GerberObject,
"excellon": ExcellonObject,
"cncjob": CNCJobObject,
"geometry": GeometryObject,
"script": ScriptObject,
"document": DocumentObject
}
log.debug("Calling object constructor...")
# Object creation/instantiation
obj = classdict[kind](name)
obj.units = self.app.options["units"]
# IMPORTANT
# The key names in defaults and options dictionary's are not random:
# they have to have in name first the type of the object (geometry, excellon, cncjob and gerber) or how it's
# called here, the 'kind' followed by an underline. Above the App default values from self.defaults are
# copied to self.options. After that, below, depending on the type of
# object that is created, it will strip the name of the object and the underline (if the original key was
# let's say "excellon_toolchange", it will strip the excellon_) and to the obj.options the key will become
# "toolchange"
for option in self.app.options:
if option.find(kind + "_") == 0:
oname = option[len(kind) + 1:]
obj.options[oname] = self.app.options[option]
obj.isHovering = False
obj.notHovering = True
# Initialize as per user request
# User must take care to implement initialize
# in a thread-safe way as is is likely that we
# have been invoked in a separate thread.
t1 = time.time()
log.debug("%f seconds before initialize()." % (t1 - t0))
try:
return_value = initialize(obj, self)
except Exception as e:
msg = '[ERROR_NOTCL] %s' % _("An internal error has occurred. See shell.\n")
msg += _("Object ({kind}) failed because: {error} \n\n").format(kind=kind, error=str(e))
msg += traceback.format_exc()
self.app.inform.emit(msg)
return "fail"
t2 = time.time()
log.debug("%f seconds executing initialize()." % (t2 - t1))
if return_value == 'fail':
log.debug("Object (%s) parsing and/or geometry creation failed." % kind)
return "fail"
# Check units and convert if necessary
# This condition CAN be true because initialize() can change obj.units
if self.app.options["units"].upper() != obj.units.upper():
self.app.inform.emit('%s: %s' % (_("Converting units to "), self.app.options["units"]))
obj.convert_units(self.app.options["units"])
t3 = time.time()
log.debug("%f seconds converting units." % (t3 - t2))
# Create the bounding box for the object and then add the results to the obj.options
# But not for Scripts or for Documents
if kind != 'document' and kind != 'script':
try:
xmin, ymin, xmax, ymax = obj.bounds()
obj.options['xmin'] = xmin
obj.options['ymin'] = ymin
obj.options['xmax'] = xmax
obj.options['ymax'] = ymax
except Exception as e:
log.warning("AppObject.new_object() -> The object has no bounds properties. %s" % str(e))
return "fail"
try:
if kind == 'excellon':
obj.fill_color = self.app.defaults["excellon_plot_fill"]
obj.outline_color = self.app.defaults["excellon_plot_line"]
if kind == 'gerber':
obj.fill_color = self.app.defaults["gerber_plot_fill"]
obj.outline_color = self.app.defaults["gerber_plot_line"]
except Exception as e:
log.warning("AppObject.new_object() -> setting colors error. %s" % str(e))
# update the KeyWords list with the name of the file
self.app.myKeywords.append(obj.options['name'])
log.debug("Moving new object back to main thread.")
# Move the object to the main thread and let the app know that it is available.
obj.moveToThread(self.app.main_thread)
self.object_created.emit(obj, obj_plot, obj_autoselected)
return obj
def new_excellon_object(self):
"""
Creates a new, blank Excellon object.
:return: None
"""
self.new_object('excellon', 'new_exc', lambda x, y: None, plot=False)
def new_geometry_object(self):
"""
Creates a new, blank and single-tool Geometry object.
:return: None
"""
def initialize(obj, app):
obj.multitool = False
self.new_object('geometry', 'new_geo', initialize, plot=False)
def new_gerber_object(self):
"""
Creates a new, blank Gerber object.
:return: None
"""
def initialize(grb_obj, app):
grb_obj.multitool = False
grb_obj.source_file = []
grb_obj.multigeo = False
grb_obj.follow = False
grb_obj.apertures = {}
grb_obj.solid_geometry = []
try:
grb_obj.options['xmin'] = 0
grb_obj.options['ymin'] = 0
grb_obj.options['xmax'] = 0
grb_obj.options['ymax'] = 0
except KeyError:
pass
self.new_object('gerber', 'new_grb', initialize, plot=False)
def new_script_object(self):
"""
Creates a new, blank TCL Script object.
:return: None
"""
# commands_list = "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, " \
# "AlignDrillGrid, Bbox, Bounds, ClearShell, CopperClear,\n" \
# "# Cncjob, Cutout, Delete, Drillcncjob, ExportDXF, ExportExcellon, ExportGcode,\n" \
# "# ExportGerber, ExportSVG, Exteriors, Follow, GeoCutout, GeoUnion, GetNames,\n" \
# "# GetSys, ImportSvg, Interiors, Isolate, JoinExcellon, JoinGeometry, " \
# "ListSys, MillDrills,\n" \
# "# MillSlots, Mirror, New, NewExcellon, NewGeometry, NewGerber, Nregions, " \
# "Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n" \
# "# Options, Paint, Panelize, PlotAl, PlotObjects, SaveProject, " \
# "SaveSys, Scale, SetActive, SetSys, SetOrigin, Skew, SubtractPoly,\n" \
# "# SubtractRectangle, Version, WriteGCode\n"
new_source_file = '# %s\n' % _('CREATE A NEW FLATCAM TCL SCRIPT') + \
'# %s:\n' % _('TCL Tutorial is here') + \
'# https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n' + '\n\n' + \
'# %s:\n' % _("FlatCAM commands list")
new_source_file += '# %s\n\n' % _("Type >help< followed by Run Code for a list of FlatCAM Tcl Commands "
"(displayed in Tcl Shell).")
def initialize(obj, app):
obj.source_file = deepcopy(new_source_file)
outname = 'new_script'
self.new_object('script', outname, initialize, plot=False)
def new_document_object(self):
"""
Creates a new, blank Document object.
:return: None
"""
def initialize(obj, app):
obj.source_file = ""
self.new_object('document', 'new_document', initialize, plot=False)
def on_object_created(self, obj, plot, auto_select):
"""
Event callback for object creation.
It will add the new object to the collection. After that it will plot the object in a threaded way
:param obj: The newly created FlatCAM object.
:param plot: if the newly create object t obe plotted
:param auto_select: if the newly created object to be autoselected after creation
:return: None
"""
t0 = time.time() # DEBUG
log.debug("on_object_created()")
# The Collection might change the name if there is a collision
self.app.collection.append(obj)
# after adding the object to the collection always update the list of objects that are in the collection
self.all_objects_list = self.app.collection.get_list()
# self.app.inform.emit('[selected] %s created & selected: %s' %
# (str(obj.kind).capitalize(), str(obj.options['name'])))
if obj.kind == 'gerber':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='green',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'excellon':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='brown',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'cncjob':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='blue',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'geometry':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='red',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'script':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='orange',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'document':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='darkCyan',
name=str(obj.options['name']), tx=_("created/selected"))
)
# update the SHELL auto-completer model with the name of the new object
self.app.shell._edit.set_model_data(self.app.myKeywords)
if auto_select:
# select the just opened object but deselect the previous ones
self.app.collection.set_all_inactive()
self.app.collection.set_active(obj.options["name"])
else:
self.app.collection.set_all_inactive()
# here it is done the object plotting
def task(t_obj):
with self.app.proc_container.new(_("Plotting")):
if t_obj.kind == 'cncjob':
t_obj.plot(kind=self.defaults["cncjob_plot_kind"])
else:
t_obj.plot()
t1 = time.time() # DEBUG
log.debug("%f seconds adding object and plotting." % (t1 - t0))
self.object_plotted.emit(t_obj)
# Send to worker
# self.worker.add_task(worker_task, [self])
if plot is True:
self.worker_task.emit({'fcn': task, 'params': [obj]})
def on_object_changed(self, obj):
"""
Called whenever the geometry of the object was changed in some way.
This require the update of it's bounding values so it can be the selected on canvas.
Update the bounding box data from obj.options
:param obj: the object that was changed
:return: None
"""
try:
xmin, ymin, xmax, ymax = obj.bounds()
except TypeError:
return
obj.options['xmin'] = xmin
obj.options['ymin'] = ymin
obj.options['xmax'] = xmax
obj.options['ymax'] = ymax
log.debug("Object changed, updating the bounding box data on self.options")
# delete the old selection shape
self.app.delete_selection_shape()
self.app.should_we_save = True
def on_object_plotted(self):
"""
Callback called whenever the plotted object needs to be fit into the viewport (canvas)
:return: None
"""
self.app.on_zoom_fit(None)

View File

@ -1196,8 +1196,8 @@ class ExcellonObject(FlatCAMObj, Excellon):
Point(hole['point']).buffer(buffer_value).exterior)
if use_thread:
def geo_thread(app_obj):
app_obj.new_object("geometry", outname, geo_init, plot=plot)
def geo_thread(a_obj):
a_obj.app_obj.new_object("geometry", outname, geo_init, plot=plot)
# Create a promise with the new name
self.app.collection.promise(outname)
@ -1205,7 +1205,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
# Send to worker
self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
else:
self.app.new_object("geometry", outname, geo_init, plot=plot)
self.app.app_obj.new_object("geometry", outname, geo_init, plot=plot)
return True, ""
@ -1300,8 +1300,8 @@ class ExcellonObject(FlatCAMObj, Excellon):
geo_obj.solid_geometry.append(poly)
if use_thread:
def geo_thread(app_obj):
app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
def geo_thread(a_obj):
a_obj.app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
# Create a promise with the new name
self.app.collection.promise(outname)
@ -1309,7 +1309,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
# Send to worker
self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
else:
self.app.new_object("geometry", outname + '_slot', geo_init, plot=plot)
self.app.app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
return True, ""
@ -1443,7 +1443,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
job_name = self.options["name"] + "_cnc"
pp_excellon_name = self.options["ppname_e"]
# Object initialization function for app.new_object()
# Object initialization function for app.app_obj.new_object()
def job_init(job_obj, app_obj):
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
@ -1506,9 +1506,9 @@ class ExcellonObject(FlatCAMObj, Excellon):
job_obj.create_geometry()
# To be run in separate thread
def job_thread(app_obj):
def job_thread(a_obj):
with self.app.proc_container.new(_("Generating CNC Code")):
app_obj.new_object("cncjob", job_name, job_init)
a_obj.app_obj.new_object("cncjob", job_name, job_init)
# Create promise for the new name.
self.app.collection.promise(job_name)

View File

@ -1778,7 +1778,7 @@ class GeometryObject(FlatCAMObj, Geometry):
self.app.inform.emit(msg)
return
# Object initialization function for app.new_object()
# Object initialization function for app.app_obj.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init_single_geometry(job_obj, app_obj):
log.debug("Creating a CNCJob out of a single-geometry")
@ -1918,7 +1918,7 @@ class GeometryObject(FlatCAMObj, Geometry):
})
dia_cnc_dict.clear()
# Object initialization function for app.new_object()
# Object initialization function for app.app_obj.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init_multi_geometry(job_obj, app_obj):
log.debug("Creating a CNCJob out of a multi-geometry")
@ -2072,15 +2072,15 @@ class GeometryObject(FlatCAMObj, Geometry):
if use_thread:
# To be run in separate thread
def job_thread(app_obj):
def job_thread(a_obj):
if self.multigeo is False:
with self.app.proc_container.new(_("Generating CNC Code")):
if app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
if a_obj.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
else:
with self.app.proc_container.new(_("Generating CNC Code")):
if app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail':
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
if a_obj.app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail':
a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
# Create a promise with the name
self.app.collection.promise(outname)
@ -2088,9 +2088,9 @@ class GeometryObject(FlatCAMObj, Geometry):
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else:
if self.solid_geometry:
self.app.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
self.app.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
else:
self.app.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
self.app.app_obj.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
def generatecncjob(self, outname=None, dia=None, offset=None, z_cut=None, z_move=None,
feedrate=None, feedrate_z=None, feedrate_rapid=None, spindlespeed=None, dwell=None, dwelltime=None,
@ -2181,7 +2181,7 @@ class GeometryObject(FlatCAMObj, Geometry):
ppname_g = pp if pp else self.options["ppname_g"]
# Object initialization function for app.new_object()
# Object initialization function for app.app_obj.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init(job_obj, app_obj):
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
@ -2230,7 +2230,7 @@ class GeometryObject(FlatCAMObj, Geometry):
# To be run in separate thread
def job_thread(app_obj):
with self.app.proc_container.new(_("Generating CNC Code")):
app_obj.new_object("cncjob", outname, job_init, plot=plot)
app_obj.app_obj.new_object("cncjob", outname, job_init, plot=plot)
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created")), outname)
# Create a promise with the name
@ -2238,7 +2238,7 @@ class GeometryObject(FlatCAMObj, Geometry):
# Send to worker
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else:
self.app.new_object("cncjob", outname, job_init, plot=plot)
self.app.app_obj.new_object("cncjob", outname, job_init, plot=plot)
# def on_plot_cb_click(self, *args):
# if self.muted_ui:

View File

@ -530,7 +530,7 @@ class GerberObject(FlatCAMObj, Gerber):
return "fail"
geo_obj.solid_geometry = non_copper
self.app.new_object("geometry", name, geo_init)
self.app.app_obj.new_object("geometry", name, geo_init)
def on_generatebb_button_click(self, *args):
self.app.defaults.report_usage("gerber_on_generatebb_button")
@ -556,7 +556,7 @@ class GerberObject(FlatCAMObj, Gerber):
return "fail"
geo_obj.solid_geometry = bounding_box
self.app.new_object("geometry", name, geo_init)
self.app.app_obj.new_object("geometry", name, geo_init)
def on_iso_button_click(self, *args):
@ -605,7 +605,7 @@ class GerberObject(FlatCAMObj, Gerber):
# TODO: Do something if this is None. Offer changing name?
try:
self.app.new_object("geometry", follow_name, follow_init)
self.app.app_obj.new_object("geometry", follow_name, follow_init)
except Exception as e:
return "Operation failed: %s" % str(e)
@ -942,7 +942,7 @@ class GerberObject(FlatCAMObj, Gerber):
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
# TODO: Do something if this is None. Offer changing name?
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot)
else:
for i in range(passes):
@ -1072,7 +1072,7 @@ class GerberObject(FlatCAMObj, Gerber):
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
# TODO: Do something if this is None. Offer changing name?
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot)
def generate_envelope(self, offset, invert, geometry=None, env_iso_type=2, follow=None, nr_passes=0):
# isolation_geometry produces an envelope that is going on the left of the geometry

View File

@ -245,7 +245,7 @@ class FlatCAMObj(QtCore.QObject):
self.app.proc_container.update_view_text('')
with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot()
self.app.object_changed.emit(self)
self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
@ -276,7 +276,7 @@ class FlatCAMObj(QtCore.QObject):
self.app.proc_container.update_view_text('')
with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot()
self.app.object_changed.emit(self)
self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
@ -292,7 +292,7 @@ class FlatCAMObj(QtCore.QObject):
self.app.proc_container.update_view_text('')
with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot()
self.app.object_changed.emit(self)
self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
@ -372,7 +372,7 @@ class FlatCAMObj(QtCore.QObject):
def plot_task():
with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot()
self.app.object_changed.emit(self)
self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': plot_task, 'params': []})

View File

@ -553,7 +553,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
while name in self.get_names():
# ## Create a new name
# Ends with number?
log.debug("new_object(): Object name (%s) exists, changing." % name)
log.debug("app_obj.new_object(): Object name (%s) exists, changing." % name)
match = re.search(r'(.*[^\d])?(\d+)$', name)
if match: # Yes: Increment the number!
base = match.group(1) or ''

View File

@ -1069,7 +1069,7 @@ class Excellon(Geometry):
This function first convert to the the units found in the Excellon file but it converts tools that
are not there yet so it has no effect other than it signal that the units are the ones in the file.
On object creation, in new_object(), true conversion is done because this is done at the end of the
On object creation, in app_obj.new_object(), true conversion is done because this is done at the end of the
Excellon file parsing, the tools are inside and self.tools is really converted from the units found
inside the file to the FlatCAM units.

View File

@ -28,7 +28,7 @@ class AppTool(QtWidgets.QWidget):
"""
:param app: The application this tool will run in.
:type app: App
:type app: AppMain
:param parent: Qt Parent
:return: AppTool
"""

View File

@ -1352,11 +1352,11 @@ class ToolCalibration(AppTool):
try:
if obj.kind.lower() == 'excellon':
self.app.new_object("excellon", str(obj_name), initialize_excellon)
self.app.app_obj.new_object("excellon", str(obj_name), initialize_excellon)
elif obj.kind.lower() == 'gerber':
self.app.new_object("gerber", str(obj_name), initialize_gerber)
self.app.app_obj.new_object("gerber", str(obj_name), initialize_gerber)
elif obj.kind.lower() == 'geometry':
self.app.new_object("geometry", str(obj_name), initialize_geometry)
self.app.app_obj.new_object("geometry", str(obj_name), initialize_geometry)
except Exception as e:
log.debug("ToolCalibration.new_calibrated_object() --> %s" % str(e))
return "Operation failed: %s" % str(e)

View File

@ -1474,7 +1474,7 @@ class ToolCopperThieving(AppTool):
obj_name, separatpr, obj_extension = self.sm_object.options['name'].rpartition('.')
name = '%s_%s.%s' % (obj_name, 'plating_mask', obj_extension)
self.app.new_object('gerber', name, obj_init, autoselected=False)
self.app.app_obj.new_object('gerber', name, obj_init, autoselected=False)
# Register recent file
self.app.file_opened.emit("gerber", name)

View File

@ -700,7 +700,7 @@ class CutOut(AppTool):
geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value()
outname = cutout_obj.options["name"] + "_cutout"
self.app.new_object('geometry', outname, geo_init)
self.app.app_obj.new_object('geometry', outname, geo_init)
cutout_obj.plot()
self.app.inform.emit('[success] %s' % _("Any form CutOut operation finished."))
@ -896,7 +896,7 @@ class CutOut(AppTool):
geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value()
outname = cutout_obj.options["name"] + "_cutout"
ret = self.app.new_object('geometry', outname, geo_init)
ret = self.app.app_obj.new_object('geometry', outname, geo_init)
if ret != 'fail':
# cutout_obj.plot()
@ -1056,7 +1056,7 @@ class CutOut(AppTool):
geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value()
outname = cutout_obj.options["name"] + "_cutout"
self.app.new_object('geometry', outname, geo_init)
self.app.app_obj.new_object('geometry', outname, geo_init)
def cutting_geo(self, pos):
self.cutting_dia = float(self.dia.get_value())

View File

@ -643,7 +643,7 @@ class DblSidedTool(AppTool):
obj_inst.source_file = app_inst.export_excellon(obj_name=obj_inst.options['name'], local_use=obj_inst,
filename=None, use_thread=False)
self.app.new_object("excellon", "Alignment Drills", obj_init)
self.app.app_obj.new_object("excellon", "Alignment Drills", obj_init)
self.drill_values = ''
self.app.inform.emit('[success] %s' % _("Excellon object with alignment drills created..."))
@ -686,7 +686,7 @@ class DblSidedTool(AppTool):
py = 0.5 * (ymin + ymax)
fcobj.mirror(axis, [px, py])
self.app.object_changed.emit(fcobj)
self.app.app_obj.object_changed.emit(fcobj)
fcobj.plot()
self.app.inform.emit('[success] Gerber %s %s...' % (str(fcobj.options['name']), _("was mirrored")))
@ -730,7 +730,7 @@ class DblSidedTool(AppTool):
py = 0.5 * (ymin + ymax)
fcobj.mirror(axis, [px, py])
self.app.object_changed.emit(fcobj)
self.app.app_obj.object_changed.emit(fcobj)
fcobj.plot()
self.app.inform.emit('[success] Excellon %s %s...' % (str(fcobj.options['name']), _("was mirrored")))
@ -767,7 +767,7 @@ class DblSidedTool(AppTool):
py = 0.5 * (ymin + ymax)
fcobj.mirror(axis, [px, py])
self.app.object_changed.emit(fcobj)
self.app.app_obj.object_changed.emit(fcobj)
fcobj.plot()
self.app.inform.emit('[success] Geometry %s %s...' % (str(fcobj.options['name']), _("was mirrored")))

View File

@ -655,7 +655,7 @@ class ToolExtractDrills(AppTool):
obj_inst.source_file = self.app.export_excellon(obj_name=outname, local_use=obj_inst, filename=None,
use_thread=False)
self.app.new_object("excellon", outname, obj_init)
self.app.app_obj.new_object("excellon", outname, obj_init)
def on_hole_size_toggle(self, val):
if val == "fixed":

View File

@ -775,7 +775,7 @@ class Film(AppTool):
new_obj.solid_geometry = deepcopy(punched_solid_geometry)
outname = name + "_punched"
self.app.new_object('gerber', outname, init_func)
self.app.app_obj.new_object('gerber', outname, init_func)
self.generate_positive_normal_film(outname, boxname, factor=factor, ftype=ftype)
else:
@ -826,7 +826,7 @@ class Film(AppTool):
new_obj.solid_geometry = deepcopy(punched_solid_geometry)
outname = name + "_punched"
self.app.new_object('gerber', outname, init_func)
self.app.app_obj.new_object('gerber', outname, init_func)
self.generate_positive_normal_film(outname, boxname, factor=factor, ftype=ftype)

View File

@ -288,7 +288,7 @@ class ToolImage(AppTool):
name = outname or filename.split('/')[-1].split('\\')[-1]
units = self.app.defaults['units']
self.app.new_object(obj_type, name, obj_init)
self.app.app_obj.new_object(obj_type, name, obj_init)
# Register recent file
self.app.file_opened.emit("image", filename)

View File

@ -293,7 +293,7 @@ class ToolInvertGerber(AppTool):
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.new_object('gerber', outname, init_func)
self.app.app_obj.new_object('gerber', outname, init_func)
def reset_fields(self):
self.gerber_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))

View File

@ -2881,12 +2881,12 @@ class NonCopperClear(AppTool, Gerber):
# ###########################################################################################
# Create the Job function and send it to the worker to be processed in another thread #######
# ###########################################################################################
def job_thread(app_obj):
def job_thread(a_obj):
try:
if rest_machining_choice is True:
app_obj.new_object("geometry", name, gen_clear_area_rest)
a_obj.app_obj.new_object("geometry", name, gen_clear_area_rest)
else:
app_obj.new_object("geometry", name, gen_clear_area)
a_obj.app_obj.new_object("geometry", name, gen_clear_area)
except grace:
if run_threaded:
proc.done()
@ -3881,9 +3881,9 @@ class NonCopperClear(AppTool, Gerber):
def job_thread(app_obj):
try:
if rest_machining_choice is True:
app_obj.new_object("geometry", name, gen_clear_area_rest, plot=plot)
app_obj.app_obj.new_object("geometry", name, gen_clear_area_rest, plot=plot)
else:
app_obj.new_object("geometry", name, gen_clear_area, plot=plot)
app_obj.app_obj.new_object("geometry", name, gen_clear_area, plot=plot)
except grace:
if run_threaded:
proc.done()

View File

@ -205,7 +205,7 @@ class ToolPDF(AppTool):
with self.app.proc_container.new(_("Rendering PDF layer #%d ...") % int(layer_nr)):
ret_val = self.app.new_object("excellon", outname, obj_init, autoselected=False)
ret_val = self.app.app_obj.new_object("excellon", outname, obj_init, autoselected=False)
if ret_val == 'fail':
self.app.inform.emit('[ERROR_NOTCL] %s' % _('Open PDF file failed.'))
return
@ -278,7 +278,7 @@ class ToolPDF(AppTool):
with self.app.proc_container.new(_("Rendering PDF layer #%d ...") % int(layer_nr)):
ret = self.app.new_object('gerber', outname, obj_init, autoselected=False)
ret = self.app.app_obj.new_object('gerber', outname, obj_init, autoselected=False)
if ret == 'fail':
self.app.inform.emit('[ERROR_NOTCL] %s' % _('Open PDF file failed.'))
return

View File

@ -2315,7 +2315,7 @@ class ToolPaint(AppTool, Gerber):
def job_thread(app_obj):
try:
ret = app_obj.new_object("geometry", name, job_init, plot=plot)
ret = app_obj.app_obj.new_object("geometry", name, job_init, plot=plot)
except grace:
proc.done()
return
@ -2823,9 +2823,9 @@ class ToolPaint(AppTool, Gerber):
def job_thread(app_obj):
try:
if self.rest_cb.isChecked():
ret = app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
ret = app_obj.app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
else:
ret = app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
ret = app_obj.app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
except grace:
proc.done()
return
@ -3320,9 +3320,9 @@ class ToolPaint(AppTool, Gerber):
def job_thread(app_obj):
try:
if self.rest_cb.isChecked():
ret = app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
ret = app_obj.app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
else:
ret = app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
ret = app_obj.app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
except grace:
proc.done()
return

View File

@ -794,9 +794,9 @@ class Panelize(AppTool):
self.app.inform.emit('%s: %d' % (_("Generating panel... Spawning copies"), (int(rows * columns))))
if panel_source_obj.kind == 'excellon':
self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
self.app.app_obj.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
else:
self.app.new_object(panel_type, self.outname, job_init_geometry, plot=True, autoselected=True)
self.app.app_obj.new_object(panel_type, self.outname, job_init_geometry, plot=True, autoselected=True)
if self.constrain_flag is False:
self.app.inform.emit('[success] %s' % _("Panel done..."))

View File

@ -452,7 +452,7 @@ class PcbWizard(AppTool):
# Object name
name = self.outname
ret_val = self.app.new_object("excellon", name, obj_init, autoselected=False)
ret_val = self.app.app_obj.new_object("excellon", name, obj_init, autoselected=False)
if ret_val == 'fail':
self.app.inform.emit('[ERROR_NOTCL] %s' % _('Import Excellon file failed.'))
return

View File

@ -591,7 +591,7 @@ class ToolPunchGerber(AppTool):
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.new_object('gerber', outname, init_func)
self.app.app_obj.new_object('gerber', outname, init_func)
elif punch_method == 'fixed':
punch_size = float(self.dia_entry.get_value())
@ -705,7 +705,7 @@ class ToolPunchGerber(AppTool):
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.new_object('gerber', outname, init_func)
self.app.app_obj.new_object('gerber', outname, init_func)
elif punch_method == 'ring':
circ_r_val = self.circular_ring_entry.get_value()
oblong_r_val = self.oblong_ring_entry.get_value()
@ -847,7 +847,7 @@ class ToolPunchGerber(AppTool):
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.new_object('gerber', outname, init_func)
self.app.app_obj.new_object('gerber', outname, init_func)
elif punch_method == 'prop':
prop_factor = self.factor_entry.get_value() / 100.0
@ -986,7 +986,7 @@ class ToolPunchGerber(AppTool):
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.new_object('gerber', outname, init_func)
self.app.app_obj.new_object('gerber', outname, init_func)
def reset_fields(self):
self.gerber_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))

View File

@ -1625,7 +1625,7 @@ class RulesCheck(AppTool):
new_obj.source_file = txt
new_obj.read_only = True
self.app.new_object('document', name='Rules Check results', initialize=init, plot=False)
self.app.app_obj.new_object('document', name='Rules Check results', initialize=init, plot=False)
def reset_fields(self):
# self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))

View File

@ -9,7 +9,7 @@ from AppTool import AppTool
from Common import LoudDict
from AppGUI.GUIElements import FCComboBox, FCEntry, FCTable, \
FCInputDialog, FCDoubleSpinner, FCSpinner, FCFileSaveDialog
from App import log
from AppMain import log
from camlib import distance
from AppEditors.FlatCAMTextEditor import TextEditor
@ -1257,7 +1257,7 @@ class SolderPaste(AppTool):
if use_thread:
def job_thread(app_obj):
try:
app_obj.new_object("geometry", name + "_solderpaste", geo_init)
app_obj.app_obj.new_object("geometry", name + "_solderpaste", geo_init)
except Exception as e:
log.error("SolderPaste.on_create_geo() --> %s" % str(e))
proc.done()
@ -1271,7 +1271,7 @@ class SolderPaste(AppTool):
# Background
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else:
self.app.new_object("geometry", name + "_solderpaste", geo_init)
self.app.app_obj.new_object("geometry", name + "_solderpaste", geo_init)
def on_create_gcode_click(self, signal):
"""
@ -1331,7 +1331,7 @@ class SolderPaste(AppTool):
self.app.inform.emit(msg)
return
# Object initialization function for app.new_object()
# Object initialization function for app.app_obj.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init(job_obj):
assert job_obj.kind == 'cncjob', \
@ -1388,7 +1388,7 @@ class SolderPaste(AppTool):
# To be run in separate thread
def job_thread(app_obj):
with self.app.proc_container.new("Generating CNC Code"):
if app_obj.new_object("cncjob", name, job_init) != 'fail':
if app_obj.app_obj.new_object("cncjob", name, job_init) != 'fail':
app_obj.inform.emit('[success] [success] %s: %s' %
(_("ToolSolderPaste CNCjob created"), name))
# Create a promise with the name
@ -1396,7 +1396,7 @@ class SolderPaste(AppTool):
# Send to worker
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else:
self.app.new_object("cncjob", name, job_init)
self.app.app_obj.new_object("cncjob", name, job_init)
def on_view_gcode(self):
"""

View File

@ -456,7 +456,7 @@ class ToolSub(AppTool):
grb_obj.follow_geometry = deepcopy(follow_buff)
with self.app.proc_container.new(_("Generating new object ...")):
ret = self.app.new_object('gerber', outname, obj_init, autoselected=False)
ret = self.app.app_obj.new_object('gerber', outname, obj_init, autoselected=False)
if ret == 'fail':
self.app.inform.emit('[ERROR_NOTCL] %s' %
_('Generating new object failed.'))
@ -659,7 +659,7 @@ class ToolSub(AppTool):
geo_obj.multigeo = False
with self.app.proc_container.new(_("Generating new object ...")):
ret = self.app.new_object('geometry', outname, obj_init, autoselected=False)
ret = self.app.app_obj.new_object('geometry', outname, obj_init, autoselected=False)
if ret == 'fail':
self.app.inform.emit('[ERROR_NOTCL] %s' %
_('Generating new object failed.'))

View File

@ -702,7 +702,7 @@ class ToolTransform(AppTool):
self.app.inform.emit(_("CNCJob objects can't be rotated."))
else:
sel_obj.rotate(-num, point=(px, py))
self.app.object_changed.emit(sel_obj)
self.app.app_obj.object_changed.emit(sel_obj)
# add information to the object that it was changed and how much
sel_obj.options['rotate'] = num
@ -776,7 +776,7 @@ class ToolTransform(AppTool):
else:
sel_obj.options['mirror_x'] = True
self.app.inform.emit('[success] %s...' % _('Flip on the X axis done'))
self.app.object_changed.emit(sel_obj)
self.app.app_obj.object_changed.emit(sel_obj)
sel_obj.plot()
except Exception as e:
self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
@ -825,7 +825,7 @@ class ToolTransform(AppTool):
sel_obj.skew(0, num, point=(xminimal, yminimal))
# add information to the object that it was changed and how much
sel_obj.options['skew_y'] = num
self.app.object_changed.emit(sel_obj)
self.app.app_obj.object_changed.emit(sel_obj)
sel_obj.plot()
self.app.inform.emit('[success] %s %s %s...' % (_('Skew on the'), str(axis), _("axis done")))
except Exception as e:
@ -878,7 +878,7 @@ class ToolTransform(AppTool):
# add information to the object that it was changed and how much
sel_obj.options['scale_x'] = xfactor
sel_obj.options['scale_y'] = yfactor
self.app.object_changed.emit(sel_obj)
self.app.app_obj.object_changed.emit(sel_obj)
sel_obj.plot()
self.app.inform.emit('[success] %s %s %s...' % (_('Scale on the'), str(axis), _('axis done')))
@ -908,7 +908,7 @@ class ToolTransform(AppTool):
sel_obj.offset((0, num))
# add information to the object that it was changed and how much
sel_obj.options['offset_y'] = num
self.app.object_changed.emit(sel_obj)
self.app.app_obj.object_changed.emit(sel_obj)
sel_obj.plot()
self.app.inform.emit('[success] %s %s %s...' % (_('Offset on the'), str(axis), _('axis done')))
@ -942,7 +942,7 @@ class ToolTransform(AppTool):
elif sel_obj.kind.lower() == 'geometry':
sel_obj.buffer(value, join, factor)
self.app.object_changed.emit(sel_obj)
self.app.app_obj.object_changed.emit(sel_obj)
sel_obj.plot()
self.app.inform.emit('[success] %s...' % _('Buffer done'))

View File

@ -20,6 +20,7 @@ CHANGELOG for FlatCAM beta
- removed reference to postprocessors and replaced it with preprocessors
- more refactoring class names
- moved some of the methods from the App class to the ObjectCollection class
- moved all the new_object related methods in their own class AppObjects.AppObject
17.05.2020
@ -4239,7 +4240,7 @@ still copper leftovers.
- modified generate_milling method which had issues from the Python3 port (it could not sort the tools due of dict to dict comparison no longer possible).
- modified the 'default' preprocessor in order to include a space between the value of Xcoord and the following Y
- made optional the using of threads for the milling command; by default it is OFF (False) because in the current configuration it creates issues when it is using threads
- modified the Panelize function and Tcl command Panelize. It was having issues due to multithreading (kept trying to modify a dictionary in redraw() method)and automatically selecting the last created object (feature introduced by me). I've added a parameter to the new_object method, named autoselected (by default it is True) and in the panelize method I initialized it with False.
- modified the Panelize function and Tcl command Panelize. It was having issues due to multithreading (kept trying to modify a dictionary in redraw() method)and automatically selecting the last created object (feature introduced by me). I've added a parameter to the app_obj.new_object method, named autoselected (by default it is True) and in the panelize method I initialized it with False.
By initializing the plot parameter with False for the temporary objects, I have increased dramatically the generation speed of the panel because now the temporary object are no longer ploted which consumed time.
- replaced log.warn() with log.warning() in camlib.py. Reason: deprecated
- fixed the issue that the "Defaults" button was having no effect when clicked and Options Combo was in Project Options

View File

@ -3,7 +3,7 @@ import os
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings, Qt
from App import App
from AppMain import App
from AppGUI import VisPyPatches
from multiprocessing import freeze_support

View File

@ -1,6 +1,6 @@
import sys
import re
import App
import AppMain
import abc
import collections
from PyQt5 import QtCore
@ -53,7 +53,7 @@ class TclCommand(object):
if self.app is None:
raise TypeError('Expected app to be FlatCAMApp instance.')
if not isinstance(self.app, App.App):
if not isinstance(self.app, AppMain.App):
raise TypeError('Expected FlatCAMApp, got %s.' % type(app))
self.log = self.app.log

View File

@ -189,7 +189,7 @@ class TclCommandAlignDrill(TclCommandSignaled):
px = 0.5 * (xmin + xmax)
py = 0.5 * (ymin + ymax)
obj.app.new_object("excellon", outname, alligndrill_init_me, plot=False)
obj.app.app_obj.new_object("excellon", outname, alligndrill_init_me, plot=False)
except Exception as e:
return "Operation failed: %s" % str(e)
@ -205,7 +205,7 @@ class TclCommandAlignDrill(TclCommandSignaled):
try:
px = dist
py = dist
obj.app.new_object("excellon", outname, alligndrill_init_me, plot=False)
obj.app.app_obj.new_object("excellon", outname, alligndrill_init_me, plot=False)
except Exception as e:
return "Operation failed: %s" % str(e)

View File

@ -111,4 +111,4 @@ class TclCommandAlignDrillGrid(TclCommandSignaled):
init_obj.create_geometry()
# Create the new object
self.app.new_object("excellon", outname, aligndrillgrid_init_me, plot=False)
self.app.app_obj.new_object("excellon", outname, aligndrillgrid_init_me, plot=False)

View File

@ -100,6 +100,6 @@ class TclCommandBbox(TclCommand):
bounding_box = bounding_box.envelope
geo_obj.solid_geometry = bounding_box
self.app.new_object("geometry", args['outname'], geo_init, plot=False)
self.app.app_obj.new_object("geometry", args['outname'], geo_init, plot=False)
except Exception as e:
return "Operation failed: %s" % str(e)

View File

@ -137,7 +137,7 @@ class TclCommandCutout(TclCommand):
geo_obj.solid_geometry = cascaded_union([LineString(segment) for segment in cuts])
try:
self.app.new_object("geometry", outname, geo_init_me, plot=False)
self.app.app_obj.new_object("geometry", outname, geo_init_me, plot=False)
self.app.inform.emit("[success] Rectangular-form Cutout operation finished.")
except Exception as e:
return "Operation failed: %s" % str(e)

View File

@ -343,4 +343,4 @@ class TclCommandDrillcncjob(TclCommandSignaled):
job_obj.gcode_parse()
job_obj.create_geometry()
self.app.new_object("cncjob", args['outname'], job_init, plot=False)
self.app.app_obj.new_object("cncjob", args['outname'], job_init, plot=False)

View File

@ -66,4 +66,4 @@ class TclCommandExteriors(TclCommandSignaled):
geo_obj.solid_geometry = obj_exteriors
obj_exteriors = obj.get_exteriors()
self.app.new_object('geometry', outname, geo_init, plot=False)
self.app.app_obj.new_object('geometry', outname, geo_init, plot=False)

View File

@ -300,11 +300,8 @@ class TclCommandGeoCutout(TclCommandSignaled):
app_obj.inform.emit("[success] %s" % _("Any-form Cutout operation finished."))
self.app.new_object('geometry', outname, geo_init, plot=False)
self.app.app_obj.new_object('geometry', outname, geo_init, plot=False)
# cutout_obj.plot()
# self.app.inform.emit("[success] Any-form Cutout operation finished.")
# self.app.plots_updated.emit()
elif cutout_obj.kind == 'gerber':
def geo_init(geo_obj, app_obj):
@ -358,7 +355,7 @@ class TclCommandGeoCutout(TclCommandSignaled):
geo_obj.options['ymax'] = cutout_obj.options['ymax']
app_obj.inform.emit("[success] %s" % _("Any-form Cutout operation finished."))
self.app.new_object('geometry', outname, geo_init, plot=False)
self.app.app_obj.new_object('geometry', outname, geo_init, plot=False)
cutout_obj = self.app.collection.get_by_name(outname)
else:

View File

@ -76,7 +76,7 @@ class TclCommandImportSvg(TclCommandSignaled):
with self.app.proc_container.new("Import SVG"):
# Object creation
self.app.new_object(obj_type, outname, obj_init, plot=False)
self.app.app_obj.new_object(obj_type, outname, obj_init, plot=False)
# Register recent file
self.app.file_opened.emit("svg", filename)

View File

@ -67,4 +67,4 @@ class TclCommandInteriors(TclCommandSignaled):
geo_obj.solid_geometry = obj_interiors
obj_interiors = obj.get_interiors()
self.app.new_object('geometry', outname, geo_init)
self.app.app_obj.new_object('geometry', outname, geo_init)

View File

@ -65,6 +65,6 @@ class TclCommandJoinExcellon(TclCommand):
ExcellonObject.merge(objs, obj_, decimals=self.app.decimals)
if objs and len(objs) >= 2:
self.app.new_object("excellon", outname, initialize, plot=False)
self.app.app_obj.new_object("excellon", outname, initialize, plot=False)
else:
return "No Excellon objects to be joined or less than two Excellon objects specified for merging."

View File

@ -65,6 +65,6 @@ class TclCommandJoinGeometry(TclCommand):
GeometryObject.merge(objs, obj_)
if objs and len(objs) >= 2:
self.app.new_object("geometry", outname, initialize, plot=False)
self.app.app_obj.new_object("geometry", outname, initialize, plot=False)
else:
return "No Geometry objects to be joined or less than two Geometry objects specified for merging."

View File

@ -58,4 +58,4 @@ class TclCommandNewExcellon(TclCommandSignaled):
name = args['name']
else:
name = 'new_exc'
self.app.new_object('excellon', name, lambda x, y: None, plot=False)
self.app.app_obj.new_object('excellon', name, lambda x, y: None, plot=False)

View File

@ -52,4 +52,4 @@ class TclCommandNewGeometry(TclCommandSignaled):
else:
name = 'new_geo'
self.app.new_object('geometry', str(name), lambda x, y: None, plot=False)
self.app.app_obj.new_object('geometry', str(name), lambda x, y: None, plot=False)

View File

@ -75,4 +75,4 @@ class TclCommandNewGerber(TclCommandSignaled):
except KeyError:
pass
self.app.new_object('gerber', name, initialize, plot=False)
self.app.app_obj.new_object('gerber', name, initialize, plot=False)

View File

@ -100,7 +100,7 @@ class TclCommandNregions(TclCommand):
non_copper = bounding_box.difference(geo)
geo_obj.solid_geometry = non_copper
self.app.new_object("geometry", args['outname'], geo_init, plot=False)
self.app.app_obj.new_object("geometry", args['outname'], geo_init, plot=False)
except Exception as e:
return "Operation failed: %s" % str(e)

View File

@ -77,10 +77,10 @@ class TclCommandOpenDXF(TclCommandSignaled):
with self.app.proc_container.new("Open DXF"):
# Object creation
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
ret_val = self.app.app_obj.new_object(obj_type, outname, obj_init, plot=False)
if ret_val == 'fail':
filename = self.app.defaults['global_tcl_path'] + '/' + outname
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
ret_val = self.app.app_obj.new_object(obj_type, outname, obj_init, plot=False)
self.app.shell.append_output(
"No path provided or path is wrong. Using the default Path... \n")

View File

@ -77,10 +77,10 @@ class TclCommandOpenSVG(TclCommandSignaled):
with self.app.proc_container.new("Import SVG"):
# Object creation
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
ret_val = self.app.app_obj.new_object(obj_type, outname, obj_init, plot=False)
if ret_val == 'fail':
filename = self.app.defaults['global_tcl_path'] + '/' + outname
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
ret_val = self.app.app_obj.new_object(obj_type, outname, obj_init, plot=False)
self.app.shell.append_output(
"No path provided or path is wrong. Using the default Path... \n")
if ret_val == 'fail':

View File

@ -167,19 +167,19 @@ class TclCommandPanelize(TclCommand):
# for col in range(columns):
# local_outname = outname + ".tmp." + str(col) + "." + str(row)
# if isinstance(obj, ExcellonObject):
# self.app.new_object("excellon", local_outname, initialize_local_excellon, plot=False,
# self.app.app_obj.new_object("excellon", local_outname, initialize_local_excellon, plot=False,
# autoselected=False)
# else:
# self.app.new_object("geometry", local_outname, initialize_local, plot=False,
# self.app.app_obj.new_object("geometry", local_outname, initialize_local, plot=False,
# autoselected=False)
#
# currentx += lenghtx
# currenty += lenghty
#
# if isinstance(obj, ExcellonObject):
# self.app.new_object("excellon", outname, initialize_excellon)
# self.app.app_obj.new_object("excellon", outname, initialize_excellon)
# else:
# self.app.new_object("geometry", outname, initialize_geometry)
# self.app.app_obj.new_object("geometry", outname, initialize_geometry)
#
# # deselect all to avoid delete selected object when run delete from shell
# self.app.collection.set_all_inactive()
@ -287,9 +287,9 @@ class TclCommandPanelize(TclCommand):
currenty += lenghty
if obj.kind == 'excellon':
self.app.new_object("excellon", outname, job_init_excellon, plot=False, autoselected=True)
self.app.app_obj.new_object("excellon", outname, job_init_excellon, plot=False, autoselected=True)
else:
self.app.new_object("geometry", outname, job_init_geometry, plot=False, autoselected=True)
self.app.app_obj.new_object("geometry", outname, job_init_geometry, plot=False, autoselected=True)
if threaded is True:
proc = self.app.proc_container.new("Generating panel ... Please wait.")

View File

@ -80,15 +80,15 @@ class TclCommandWriteGCode(TclCommandSignaled):
# This is not needed any more? All targets should be present.
# If there are promised objects, wait until all promises have been fulfilled.
# if self.collection.has_promises():
# def write_gcode_on_object(new_object):
# def write_gcode_on_object(app_obj.new_object):
# self.log.debug("write_gcode_on_object(): Disconnecting %s" % write_gcode_on_object)
# self.new_object_available.disconnect(write_gcode_on_object)
# self.app_obj.new_object_available.disconnect(write_gcode_on_object)
# write_gcode(obj_name, filename, preamble, postamble)
#
# # Try again when a new object becomes available.
# self.log.debug("write_gcode(): Collection has promises. Queued for %s." % obj_name)
# self.log.debug("write_gcode(): Queued function: %s" % write_gcode_on_object)
# self.new_object_available.connect(write_gcode_on_object)
# self.app_obj.new_object_available.connect(write_gcode_on_object)
#
# return