- trying to make loading a project an easier task for the application
This commit is contained in:
@@ -7,6 +7,10 @@ CHANGELOG for FlatCAM Evo beta
|
|||||||
|
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
27.03.2022
|
||||||
|
|
||||||
|
- trying to make loading a project an easier task for the application
|
||||||
|
|
||||||
24.03.2022
|
24.03.2022
|
||||||
|
|
||||||
- refactoring names for some classes
|
- refactoring names for some classes
|
||||||
|
|||||||
100
appMain.py
100
appMain.py
@@ -226,21 +226,16 @@ class App(QtCore.QObject):
|
|||||||
file_opened = QtCore.pyqtSignal(str, str)
|
file_opened = QtCore.pyqtSignal(str, str)
|
||||||
# File type and filename
|
# File type and filename
|
||||||
file_saved = QtCore.pyqtSignal(str, str)
|
file_saved = QtCore.pyqtSignal(str, str)
|
||||||
|
|
||||||
# close app signal
|
# close app signal
|
||||||
close_app_signal = pyqtSignal()
|
close_app_signal = pyqtSignal()
|
||||||
|
|
||||||
# will perform the cleanup operation after a Graceful Exit
|
# will perform the cleanup operation after a Graceful Exit
|
||||||
# usefull for the NCC Tool and Paint Tool where some progressive plotting might leave
|
# usefull for the NCC Tool and Paint Tool where some progressive plotting might leave
|
||||||
# graphic residues behind
|
# graphic residues behind
|
||||||
cleanup = pyqtSignal()
|
cleanup = pyqtSignal()
|
||||||
|
|
||||||
# emitted when the new_project is created in a threaded way
|
# emitted when the new_project is created in a threaded way
|
||||||
new_project_signal = pyqtSignal()
|
new_project_signal = pyqtSignal()
|
||||||
|
|
||||||
# Percentage of progress
|
# Percentage of progress
|
||||||
progress = QtCore.pyqtSignal(int)
|
progress = QtCore.pyqtSignal(int)
|
||||||
|
|
||||||
# Emitted when a new object has been added or deleted from/to the collection
|
# Emitted when a new object has been added or deleted from/to the collection
|
||||||
object_status_changed = QtCore.pyqtSignal(object, str, str)
|
object_status_changed = QtCore.pyqtSignal(object, str, str)
|
||||||
|
|
||||||
@@ -248,31 +243,28 @@ class App(QtCore.QObject):
|
|||||||
|
|
||||||
# Emmited when shell command is finished(one command only)
|
# Emmited when shell command is finished(one command only)
|
||||||
shell_command_finished = QtCore.pyqtSignal(object)
|
shell_command_finished = QtCore.pyqtSignal(object)
|
||||||
|
|
||||||
# Emitted when multiprocess pool has been recreated
|
# Emitted when multiprocess pool has been recreated
|
||||||
pool_recreated = QtCore.pyqtSignal(object)
|
pool_recreated = QtCore.pyqtSignal(object)
|
||||||
|
|
||||||
# Emitted when an unhandled exception happens
|
# Emitted when an unhandled exception happens
|
||||||
# in the worker task.
|
# in the worker task.
|
||||||
thread_exception = QtCore.pyqtSignal(object)
|
thread_exception = QtCore.pyqtSignal(object)
|
||||||
|
|
||||||
# used to signal that there are arguments for the app
|
# used to signal that there are arguments for the app
|
||||||
args_at_startup = QtCore.pyqtSignal(list)
|
args_at_startup = QtCore.pyqtSignal(list)
|
||||||
|
|
||||||
# a reusable signal to replot a list of objects
|
# a reusable signal to replot a list of objects
|
||||||
# should be disconnected after use so it can be reused
|
# should be disconnected after use so it can be reused
|
||||||
replot_signal = pyqtSignal(list)
|
replot_signal = pyqtSignal(list)
|
||||||
|
|
||||||
# signal emitted when jumping
|
# signal emitted when jumping
|
||||||
jump_signal = pyqtSignal(tuple)
|
jump_signal = pyqtSignal(tuple)
|
||||||
|
|
||||||
# signal emitted when jumping
|
# signal emitted when jumping
|
||||||
locate_signal = pyqtSignal(tuple, str)
|
locate_signal = pyqtSignal(tuple, str)
|
||||||
|
|
||||||
proj_selection_changed = pyqtSignal(object, object)
|
proj_selection_changed = pyqtSignal(object, object)
|
||||||
|
# used by the AppScript object to process a script
|
||||||
# used by the FlatCAMScript object to process a script
|
|
||||||
run_script = pyqtSignal(str)
|
run_script = pyqtSignal(str)
|
||||||
|
# used when loading a project and parsing the project file
|
||||||
|
restore_project = pyqtSignal(object, str, bool, bool, bool, bool)
|
||||||
|
# used when loading a project and restoring objects
|
||||||
|
restore_project_objects_sig = pyqtSignal(object, str, bool, bool)
|
||||||
|
|
||||||
def __init__(self, qapp, user_defaults=True):
|
def __init__(self, qapp, user_defaults=True):
|
||||||
"""
|
"""
|
||||||
@@ -1411,6 +1403,9 @@ class App(QtCore.QObject):
|
|||||||
|
|
||||||
# signals for displaying messages in the Tcl Shell are now connected in the ToolShell class
|
# signals for displaying messages in the Tcl Shell are now connected in the ToolShell class
|
||||||
|
|
||||||
|
# loading an project
|
||||||
|
self.restore_project.connect(self.f_handlers.restore_project_handler)
|
||||||
|
self.restore_project_objects_sig.connect(self.f_handlers.restore_project_objects)
|
||||||
# signal to be called when the app is quiting
|
# signal to be called when the app is quiting
|
||||||
self.app_quit.connect(self.quit_application, type=Qt.ConnectionType.QueuedConnection)
|
self.app_quit.connect(self.quit_application, type=Qt.ConnectionType.QueuedConnection)
|
||||||
self.message.connect(
|
self.message.connect(
|
||||||
@@ -1494,7 +1489,6 @@ class App(QtCore.QObject):
|
|||||||
# ###########################################################################################################
|
# ###########################################################################################################
|
||||||
# ####################################### FILE ASSOCIATIONS SIGNALS #########################################
|
# ####################################### FILE ASSOCIATIONS SIGNALS #########################################
|
||||||
# ###########################################################################################################
|
# ###########################################################################################################
|
||||||
|
|
||||||
self.ui.util_pref_form.fa_excellon_group.restore_btn.clicked.connect(
|
self.ui.util_pref_form.fa_excellon_group.restore_btn.clicked.connect(
|
||||||
lambda: self.restore_extensions(ext_type='excellon'))
|
lambda: self.restore_extensions(ext_type='excellon'))
|
||||||
self.ui.util_pref_form.fa_gcode_group.restore_btn.clicked.connect(
|
self.ui.util_pref_form.fa_gcode_group.restore_btn.clicked.connect(
|
||||||
@@ -2119,12 +2113,13 @@ class App(QtCore.QObject):
|
|||||||
self.ui.menu_plugins_shell.triggered.connect(self.ui.toggle_shell_ui)
|
self.ui.menu_plugins_shell.triggered.connect(self.ui.toggle_shell_ui)
|
||||||
|
|
||||||
# third install all of them
|
# third install all of them
|
||||||
|
t0 = time.time()
|
||||||
try:
|
try:
|
||||||
self.install_tools(init_tcl=init_tcl)
|
self.install_tools(init_tcl=init_tcl)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.log.debug("Tools are initialized.")
|
self.log.debug("%s: %s" % ("Tools are initialized in", str(time.time() - t0)))
|
||||||
|
|
||||||
# def parse_system_fonts(self):
|
# def parse_system_fonts(self):
|
||||||
# self.worker_task.emit({'fcn': self.f_parse.get_fonts_by_types,
|
# self.worker_task.emit({'fcn': self.f_parse.get_fonts_by_types,
|
||||||
@@ -10245,7 +10240,7 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
|
|
||||||
self.log.debug("on_file_new_project()")
|
self.log.debug("on_file_new_project()")
|
||||||
|
|
||||||
t0 = time.time()
|
t_start_proj = time.time()
|
||||||
|
|
||||||
# close any editor that might be open
|
# close any editor that might be open
|
||||||
if self.app.call_source != 'app':
|
if self.app.call_source != 'app':
|
||||||
@@ -10281,7 +10276,7 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
# delete any selection shape on canvas
|
# delete any selection shape on canvas
|
||||||
self.app.delete_selection_shape()
|
self.app.delete_selection_shape()
|
||||||
|
|
||||||
# delete all FlatCAM objects
|
# delete all App objects
|
||||||
if keep_scripts is True:
|
if keep_scripts is True:
|
||||||
for prj_obj in self.app.collection.get_list():
|
for prj_obj in self.app.collection.get_list():
|
||||||
if prj_obj.kind != 'script':
|
if prj_obj.kind != 'script':
|
||||||
@@ -10289,6 +10284,9 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
else:
|
else:
|
||||||
self.app.collection.delete_all()
|
self.app.collection.delete_all()
|
||||||
|
|
||||||
|
self.log.debug('%s: %s %s.' %
|
||||||
|
("Deleted all the application objects", str(time.time() - t_start_proj), _("seconds")))
|
||||||
|
|
||||||
# add in Selected tab an initial text that describe the flow of work in FlatCAm
|
# add in Selected tab an initial text that describe the flow of work in FlatCAm
|
||||||
self.app.setup_default_properties_tab()
|
self.app.setup_default_properties_tab()
|
||||||
|
|
||||||
@@ -10305,6 +10303,7 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
if use_thread is True:
|
if use_thread is True:
|
||||||
self.app.new_project_signal.emit()
|
self.app.new_project_signal.emit()
|
||||||
else:
|
else:
|
||||||
|
t0 = time.time()
|
||||||
# Clear pool
|
# Clear pool
|
||||||
self.app.clear_pool()
|
self.app.clear_pool()
|
||||||
|
|
||||||
@@ -10313,6 +10312,8 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
self.app.init_tools(init_tcl=True)
|
self.app.init_tools(init_tcl=True)
|
||||||
else:
|
else:
|
||||||
self.app.init_tools(init_tcl=False)
|
self.app.init_tools(init_tcl=False)
|
||||||
|
self.log.debug(
|
||||||
|
'%s: %s %s.' % ("Initiated the MP pool and plugins in: ", str(time.time() - t0), _("seconds")))
|
||||||
|
|
||||||
# tcl needs to be reinitialized, otherwise old shell variables etc remains
|
# tcl needs to be reinitialized, otherwise old shell variables etc remains
|
||||||
# self.app.shell.init_tcl()
|
# self.app.shell.init_tcl()
|
||||||
@@ -10336,7 +10337,7 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
# take the focus of the Notebook on Project Tab.
|
# take the focus of the Notebook on Project Tab.
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
||||||
|
|
||||||
self.log.debug('%s: %s %s.' % (_("Project created in"), str(time.time() - t0), _("seconds")))
|
self.log.debug('%s: %s %s.' % (_("Project created in"), str(time.time() - t_start_proj), _("seconds")))
|
||||||
self.app.ui.set_ui_title(name=_("New Project - Not saved"))
|
self.app.ui.set_ui_title(name=_("New Project - Not saved"))
|
||||||
|
|
||||||
self.inform.emit('[success] %s...' % _("New Project created"))
|
self.inform.emit('[success] %s...' % _("New Project created"))
|
||||||
@@ -10348,6 +10349,7 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
:return:
|
:return:
|
||||||
:rtype:
|
:rtype:
|
||||||
"""
|
"""
|
||||||
|
t0 = time.time()
|
||||||
|
|
||||||
# Clear pool
|
# Clear pool
|
||||||
self.log.debug("New Project: cleaning multiprocessing pool.")
|
self.log.debug("New Project: cleaning multiprocessing pool.")
|
||||||
@@ -10356,6 +10358,7 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
# Init FlatCAMTools
|
# Init FlatCAMTools
|
||||||
self.log.debug("New Project: initializing the Tools and Tcl Shell.")
|
self.log.debug("New Project: initializing the Tools and Tcl Shell.")
|
||||||
self.app.init_tools(init_tcl=True)
|
self.app.init_tools(init_tcl=True)
|
||||||
|
self.log.debug('%s: %s %s.' % ("Initiated the MP pool and plugins in: ", str(time.time() - t0), _("seconds")))
|
||||||
|
|
||||||
def on_filenewscript(self, silent=False):
|
def on_filenewscript(self, silent=False):
|
||||||
"""
|
"""
|
||||||
@@ -11854,7 +11857,7 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open config file"), filename))
|
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open config file"), filename))
|
||||||
return
|
return
|
||||||
|
|
||||||
def open_project(self, filename, run_from_arg=None, plot=True, cli=None, from_tcl=False):
|
def open_project(self, filename, run_from_arg=False, plot=True, cli=False, from_tcl=False):
|
||||||
"""
|
"""
|
||||||
Loads a project from the specified file.
|
Loads a project from the specified file.
|
||||||
|
|
||||||
@@ -11872,8 +11875,11 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
:param from_tcl: True if run from Tcl Sehll
|
:param from_tcl: True if run from Tcl Sehll
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
self.log.debug("Opening project: " + filename)
|
|
||||||
if not os.path.exists(filename):
|
project_filename = filename
|
||||||
|
|
||||||
|
self.log.debug("Opening project: " + project_filename)
|
||||||
|
if not os.path.exists(project_filename):
|
||||||
self.inform.emit('[ERROR_NOTCL] %s' % _("File no longer available."))
|
self.inform.emit('[ERROR_NOTCL] %s' % _("File no longer available."))
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -11893,22 +11899,24 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
alignment=Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignLeft,
|
alignment=Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignLeft,
|
||||||
color=QtGui.QColor("lightgray"))
|
color=QtGui.QColor("lightgray"))
|
||||||
|
|
||||||
|
def parse_worker(prj_filename):
|
||||||
|
with self.app.proc_container.new('%s' % _("Parsing...")):
|
||||||
# Open and parse an uncompressed Project file
|
# Open and parse an uncompressed Project file
|
||||||
try:
|
try:
|
||||||
f = open(filename, 'r')
|
f = open(prj_filename, 'r')
|
||||||
except IOError:
|
except IOError:
|
||||||
if from_tcl:
|
if from_tcl:
|
||||||
name = filename.split('/')[-1].split('\\')[-1]
|
name = prj_filename.split('/')[-1].split('\\')[-1]
|
||||||
filename = self.options['global_tcl_path'] + '/' + name
|
prj_filename = os.path.join(self.options['global_tcl_path'], name)
|
||||||
try:
|
try:
|
||||||
f = open(filename, 'r')
|
f = open(prj_filename, 'r')
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.error("Failed to open project file: %s" % filename)
|
self.log.error("Failed to open project file: %s" % prj_filename)
|
||||||
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open project file"), filename))
|
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open project file"), prj_filename))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.log.error("Failed to open project file: %s" % filename)
|
self.log.error("Failed to open project file: %s" % prj_filename)
|
||||||
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open project file"), filename))
|
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open project file"), prj_filename))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -11916,17 +11924,17 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
"Failed to parse project file, trying to see if it loads as an LZMA archive: %s because %s" %
|
"Failed to parse project file, trying to see if it loads as an LZMA archive: %s because %s" %
|
||||||
(filename, str(e)))
|
(prj_filename, str(e)))
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# Open and parse a compressed Project file
|
# Open and parse a compressed Project file
|
||||||
try:
|
try:
|
||||||
with lzma.open(filename) as f:
|
with lzma.open(prj_filename) as f:
|
||||||
file_content = f.read().decode('utf-8')
|
file_content = f.read().decode('utf-8')
|
||||||
d = json.loads(file_content, object_hook=dict2obj)
|
d = json.loads(file_content, object_hook=dict2obj)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.error("Failed to open project file: %s with error: %s" % (filename, str(e)))
|
self.log.error("Failed to open project file: %s with error: %s" % (prj_filename, str(e)))
|
||||||
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open project file"), filename))
|
self.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open project file"), prj_filename))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check for older projects
|
# Check for older projects
|
||||||
@@ -11965,6 +11973,11 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
self.app.log.error("Legacy Project. Loading not supported.")
|
self.app.log.error("Legacy Project. Loading not supported.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.app.restore_project.emit(d, prj_filename, run_from_arg, from_tcl, cli, plot)
|
||||||
|
|
||||||
|
self.app.worker_task.emit({'fcn': parse_worker, 'params': [project_filename]})
|
||||||
|
|
||||||
|
def restore_project_handler(self, proj_dict, filename, run_from_arg, from_tcl, cli, plot):
|
||||||
# Clear the current project
|
# Clear the current project
|
||||||
# # NOT THREAD SAFE # ##
|
# # NOT THREAD SAFE # ##
|
||||||
if run_from_arg is True:
|
if run_from_arg is True:
|
||||||
@@ -11996,13 +12009,13 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
# self.app.defaults.update(self.app.options)
|
# self.app.defaults.update(self.app.options)
|
||||||
# self.app.preferencesUiManager.save_defaults()
|
# self.app.preferencesUiManager.save_defaults()
|
||||||
# Project options
|
# Project options
|
||||||
self.app.options.update(d['options'])
|
self.app.options.update(proj_dict['options'])
|
||||||
if response == bt_no:
|
if response == bt_no:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# Load by default new options when not using GUI
|
# Load by default new options when not using GUI
|
||||||
# Project options
|
# Project options
|
||||||
self.app.options.update(d['options'])
|
self.app.options.update(proj_dict['options'])
|
||||||
|
|
||||||
self.app.project_filename = filename
|
self.app.project_filename = filename
|
||||||
|
|
||||||
@@ -12011,10 +12024,15 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
if cli is None:
|
if cli is None:
|
||||||
self.app.set_screen_units(self.app.options["units"])
|
self.app.set_screen_units(self.app.options["units"])
|
||||||
|
|
||||||
|
self.app.restore_project_objects_sig.emit(proj_dict, filename, cli, plot)
|
||||||
|
|
||||||
|
def restore_project_objects(self, proj_dict, filename, cli, plot):
|
||||||
|
|
||||||
|
def worker_task():
|
||||||
|
with self.app.proc_container.new('%s' % _("Loading...")):
|
||||||
# Re create objects
|
# Re create objects
|
||||||
self.log.debug(" **************** Started PROEJCT loading... **************** ")
|
self.log.debug(" **************** Started PROEJCT loading... **************** ")
|
||||||
|
for obj in proj_dict['objs']:
|
||||||
for obj in d['objs']:
|
|
||||||
try:
|
try:
|
||||||
msg = "Recreating from opened project an %s object: %s" % \
|
msg = "Recreating from opened project an %s object: %s" % \
|
||||||
(obj['kind'].capitalize(), obj['obj_options']['name'])
|
(obj['kind'].capitalize(), obj['obj_options']['name'])
|
||||||
@@ -12025,9 +12043,6 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
self.app.log.debug(msg)
|
self.app.log.debug(msg)
|
||||||
|
|
||||||
def obj_init(new_obj, app_inst):
|
def obj_init(new_obj, app_inst):
|
||||||
|
|
||||||
def worker_task():
|
|
||||||
with app_inst.proc_container.new('%s...' % _("Opening")):
|
|
||||||
try:
|
try:
|
||||||
new_obj.from_dict(obj)
|
new_obj.from_dict(obj)
|
||||||
except Exception as erro:
|
except Exception as erro:
|
||||||
@@ -12100,9 +12115,6 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
# CNCJob.set_ui()
|
# CNCJob.set_ui()
|
||||||
new_obj.is_loaded_from_project = True
|
new_obj.is_loaded_from_project = True
|
||||||
|
|
||||||
worker_task()
|
|
||||||
# app_inst.worker_task.emit({'fcn': worker_task, 'params': []})
|
|
||||||
|
|
||||||
# for some reason, setting ui_title does not work when this method is called from Tcl Shell
|
# for some reason, setting ui_title does not work when this method is called from Tcl Shell
|
||||||
# it's because the TclCommand is run in another thread (it inherits TclCommandSignaled)
|
# it's because the TclCommand is run in another thread (it inherits TclCommandSignaled)
|
||||||
try:
|
try:
|
||||||
@@ -12138,6 +12150,8 @@ class MenuFileHandlers(QtCore.QObject):
|
|||||||
|
|
||||||
self.log.debug(" **************** Finished PROJECT loading... **************** ")
|
self.log.debug(" **************** Finished PROJECT loading... **************** ")
|
||||||
|
|
||||||
|
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||||
|
|
||||||
def save_project(self, filename, quit_action=False, silent=False, from_tcl=False):
|
def save_project(self, filename, quit_action=False, silent=False, from_tcl=False):
|
||||||
"""
|
"""
|
||||||
Saves the current project to the specified file.
|
Saves the current project to the specified file.
|
||||||
|
|||||||
Reference in New Issue
Block a user