mirror of
https://git.salome-platform.org/gitpub/modules/geom.git
synced 2025-01-13 10:10:34 +05:00
[bos #38044][EDF] (2023-T3) Support for automatic reparation. Emitter now returns bool value that is False if the job was canceled. It should be used for early return from the running script to finish the thread gracefully. A timer was added to terminate the thread as a last resort.
This commit is contained in:
parent
674f0de7ce
commit
d270b0ab08
@ -98,8 +98,7 @@ class RepairProgressDialog(QDialog, QPlainTextEdit):
|
|||||||
self.close()
|
self.close()
|
||||||
else:
|
else:
|
||||||
# Terminates the execution of the thread.
|
# Terminates the execution of the thread.
|
||||||
# TODO: find out if we can do it with requestInterruption()
|
self.thread.cancel()
|
||||||
self.thread.terminate()
|
|
||||||
|
|
||||||
self.progress.setLabelText('Canceled!')
|
self.progress.setLabelText('Canceled!')
|
||||||
self.progress.setCancelButtonText('Close')
|
self.progress.setCancelButtonText('Close')
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
import inspect
|
import inspect
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
|
|
||||||
from qtsalome import QApplication, pyqtSignal, QThread, Qt
|
from qtsalome import QApplication, pyqtSignal, QThread, Qt, QTimer
|
||||||
from .geomrepairadv_logger import logger
|
from .geomrepairadv_logger import logger
|
||||||
|
|
||||||
|
|
||||||
@ -58,6 +58,11 @@ class Worker(QThread):
|
|||||||
# Set a variable for result
|
# Set a variable for result
|
||||||
self.result = None
|
self.result = None
|
||||||
|
|
||||||
|
# Create a timer to terminate the thread if we can't exit gracefully
|
||||||
|
self.terminate_timer = QTimer()
|
||||||
|
self.terminate_timer.timeout.connect(self.terminate)
|
||||||
|
self.terminate_timer.setSingleShot(True)
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
"""
|
||||||
@ -72,7 +77,9 @@ class Worker(QThread):
|
|||||||
|
|
||||||
# Reset the progress when finished
|
# Reset the progress when finished
|
||||||
self.progress_update.emit(100)
|
self.progress_update.emit(100)
|
||||||
self.work_completed.emit()
|
|
||||||
|
if not self.is_canceled():
|
||||||
|
self.work_completed.emit()
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error(format_exc())
|
logger.error(format_exc())
|
||||||
@ -82,15 +89,41 @@ class Worker(QThread):
|
|||||||
QApplication.restoreOverrideCursor()
|
QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
|
|
||||||
|
def is_canceled(self):
|
||||||
|
"""
|
||||||
|
Returns true if the job was canceled.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return not self.progress_emitter.is_running
|
||||||
|
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
"""
|
||||||
|
Cancels the job.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Set emitter to know that we canceled the job and
|
||||||
|
# can return from the running function gracefully.
|
||||||
|
self.progress_emitter.stop()
|
||||||
|
|
||||||
|
# Termination doesn't call a final block inside run()
|
||||||
|
QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
|
# Set a timer for a case when the running function
|
||||||
|
# doesn't use emitter or does so heavy job that it would take
|
||||||
|
# a lot of time for waiting and we need to terminate it.
|
||||||
|
self.terminate_timer.start(1000)
|
||||||
|
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
"""
|
"""
|
||||||
Overrides default terminate() to add some clean up.
|
Overrides default terminate() to add some clean up.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().terminate()
|
# Check if the job is still running and need to be terminated
|
||||||
|
if self.isRunning():
|
||||||
# Termination doesn't call a final block inside run()
|
logger.warning('Thread will be terminated!')
|
||||||
QApplication.restoreOverrideCursor()
|
super().terminate()
|
||||||
|
|
||||||
|
|
||||||
def get_result(self):
|
def get_result(self):
|
||||||
@ -114,11 +147,25 @@ class ProgressEmitter():
|
|||||||
self.progress_percent = total_lines / 100.0
|
self.progress_percent = total_lines / 100.0
|
||||||
logger.debug('self.progress_percent: %f', self.progress_percent)
|
logger.debug('self.progress_percent: %f', self.progress_percent)
|
||||||
|
|
||||||
|
# Flag to check if we need to return from a function running in the thread
|
||||||
|
self.is_running = True
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""
|
||||||
|
Call this methid from the Worker for early return
|
||||||
|
from a function executed in the separated thread.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.is_running = False
|
||||||
|
|
||||||
|
|
||||||
def emit(self):
|
def emit(self):
|
||||||
"""
|
"""
|
||||||
Call this methid in a target function to update a progress value
|
Call this methid in a target function to update a progress value
|
||||||
based on a currently executed line number.
|
based on a currently executed line number.
|
||||||
|
Returns False if the job was stopped. Should be used in the algo scripts
|
||||||
|
for early return from the running function and finish the thread.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
line = inspect.getframeinfo(inspect.stack()[1][0]).lineno
|
line = inspect.getframeinfo(inspect.stack()[1][0]).lineno
|
||||||
@ -127,3 +174,5 @@ class ProgressEmitter():
|
|||||||
logger.debug('progress_value: %d', progress_value)
|
logger.debug('progress_value: %d', progress_value)
|
||||||
|
|
||||||
self.progress_update.emit(int(progress_value))
|
self.progress_update.emit(int(progress_value))
|
||||||
|
|
||||||
|
return self.is_running
|
||||||
|
@ -45,10 +45,10 @@ class Reparation_plugin(BaseDlg):
|
|||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
# Min/max values widgets
|
# Min/max values widgets
|
||||||
decimals = 2
|
decimals = 7
|
||||||
max_value = sys.float_info.max
|
max_value = sys.float_info.max
|
||||||
self._min_widget = DlgRef_1Spin_QTD('Tol Min', 0, decimals, max_value)
|
self._min_widget = DlgRef_1Spin_QTD('Tol Min', 0.001, decimals, max_value)
|
||||||
self._max_widget = DlgRef_1Spin_QTD('Tol Max', 1000, decimals, max_value)
|
self._max_widget = DlgRef_1Spin_QTD('Tol Max', 0.015, decimals, max_value)
|
||||||
self._min_widget.SpinBox_DX.valueChanged.connect(self.on_limit_changed)
|
self._min_widget.SpinBox_DX.valueChanged.connect(self.on_limit_changed)
|
||||||
self._max_widget.SpinBox_DX.valueChanged.connect(self.on_limit_changed)
|
self._max_widget.SpinBox_DX.valueChanged.connect(self.on_limit_changed)
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ from salome.geom import geomBuilder
|
|||||||
from qtsalome import QFileDialog, QApplication, pyqtSignal
|
from qtsalome import QFileDialog, QApplication, pyqtSignal
|
||||||
import GEOM
|
import GEOM
|
||||||
|
|
||||||
|
|
||||||
salome.salome_init()
|
salome.salome_init()
|
||||||
geompy = geomBuilder.New()
|
geompy = geomBuilder.New()
|
||||||
|
|
||||||
@ -53,9 +52,7 @@ def run(args_dict, progress_emitter):
|
|||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
if ('source_solid' not in args_dict or
|
if ('source_solid' not in args_dict or
|
||||||
'selected_ids' not in args_dict or
|
|
||||||
'result_name' not in args_dict or
|
'result_name' not in args_dict or
|
||||||
'selection_level' not in args_dict or
|
|
||||||
'Tol_min' not in args_dict or
|
'Tol_min' not in args_dict or
|
||||||
'Tol_max' not in args_dict or
|
'Tol_max' not in args_dict or
|
||||||
'Debug' not in args_dict):
|
'Debug' not in args_dict):
|
||||||
@ -64,45 +61,28 @@ def run(args_dict, progress_emitter):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
source_solid = args_dict['source_solid']
|
source_solid = args_dict['source_solid']
|
||||||
selected_ids = args_dict['selected_ids']
|
|
||||||
result_name = args_dict['result_name']
|
result_name = args_dict['result_name']
|
||||||
selection_level = args_dict['selection_level']
|
minTol = args_dict['Tol_min']
|
||||||
Tol_min = args_dict['Tol_min']
|
maxTol = args_dict['Tol_max']
|
||||||
Tol_max = args_dict['Tol_max']
|
|
||||||
Debug = args_dict['Debug']
|
Debug = args_dict['Debug']
|
||||||
|
|
||||||
# Replace the lines below with an actual algorithm
|
# Replace the lines below with an actual algorithm
|
||||||
logging.info('Received arguments:')
|
logging.info('Received arguments:')
|
||||||
logging.info('\tsource_solid: %s', source_solid)
|
logging.info('\tsource_solid: %s', source_solid)
|
||||||
logging.info('\tselected_ids: %s', selected_ids)
|
|
||||||
logging.info('\tresult_name: %s', result_name)
|
logging.info('\tresult_name: %s', result_name)
|
||||||
logging.info('\tselection_level: %s', selection_level)
|
logging.info('\Tol_min: %s', minTol)
|
||||||
logging.info('\Tol_min: %s', Tol_min)
|
logging.info('\Tol_max: %s', maxTol)
|
||||||
logging.info('\Tol_max: %s', Tol_max)
|
|
||||||
logging.info('\Debug: %s', Debug)
|
logging.info('\Debug: %s', Debug)
|
||||||
|
|
||||||
progress_emitter.emit()
|
progress_emitter.emit()
|
||||||
sleep(1)
|
|
||||||
|
|
||||||
# Make a group
|
for i in range(5000):
|
||||||
# geomBuilder uses their own types - geomBuilder.ShapeType
|
vertex = geompy.MakeVertex(0,0,0)
|
||||||
geom_builder_types = { GEOM.EDGE : 'EDGE', GEOM.FACE : 'FACE', GEOM.SOLID : 'SOLID' }
|
logging.info('\I: %s', i)
|
||||||
type_str = geom_builder_types[selection_level]
|
if not progress_emitter.emit():
|
||||||
shape_type = geompy.ShapeType[type_str]
|
return False
|
||||||
group = geompy.CreateGroup(source_solid, shape_type, theName = result_name)
|
|
||||||
|
|
||||||
logging.info('Step1.')
|
return vertex
|
||||||
progress_emitter.emit()
|
|
||||||
sleep(1)
|
|
||||||
|
|
||||||
# Add sub-shapes into the group
|
|
||||||
for subshape_id in selected_ids:
|
|
||||||
geompy.AddObject(group, subshape_id)
|
|
||||||
|
|
||||||
logging.info('Step2.')
|
|
||||||
progress_emitter.emit()
|
|
||||||
|
|
||||||
return group
|
|
||||||
|
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
|
Loading…
Reference in New Issue
Block a user