mirror of
https://git.salome-platform.org/gitpub/modules/geom.git
synced 2024-12-25 17:00:35 +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()
|
||||
else:
|
||||
# Terminates the execution of the thread.
|
||||
# TODO: find out if we can do it with requestInterruption()
|
||||
self.thread.terminate()
|
||||
self.thread.cancel()
|
||||
|
||||
self.progress.setLabelText('Canceled!')
|
||||
self.progress.setCancelButtonText('Close')
|
||||
|
@ -22,7 +22,7 @@
|
||||
import inspect
|
||||
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
|
||||
|
||||
|
||||
@ -58,6 +58,11 @@ class Worker(QThread):
|
||||
# Set a variable for result
|
||||
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):
|
||||
"""
|
||||
@ -72,7 +77,9 @@ class Worker(QThread):
|
||||
|
||||
# Reset the progress when finished
|
||||
self.progress_update.emit(100)
|
||||
self.work_completed.emit()
|
||||
|
||||
if not self.is_canceled():
|
||||
self.work_completed.emit()
|
||||
|
||||
except Exception:
|
||||
logger.error(format_exc())
|
||||
@ -82,15 +89,41 @@ class Worker(QThread):
|
||||
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):
|
||||
"""
|
||||
Overrides default terminate() to add some clean up.
|
||||
"""
|
||||
|
||||
super().terminate()
|
||||
|
||||
# Termination doesn't call a final block inside run()
|
||||
QApplication.restoreOverrideCursor()
|
||||
# Check if the job is still running and need to be terminated
|
||||
if self.isRunning():
|
||||
logger.warning('Thread will be terminated!')
|
||||
super().terminate()
|
||||
|
||||
|
||||
def get_result(self):
|
||||
@ -114,11 +147,25 @@ class ProgressEmitter():
|
||||
self.progress_percent = total_lines / 100.0
|
||||
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):
|
||||
"""
|
||||
Call this methid in a target function to update a progress value
|
||||
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
|
||||
@ -127,3 +174,5 @@ class ProgressEmitter():
|
||||
logger.debug('progress_value: %d', 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)
|
||||
|
||||
# Min/max values widgets
|
||||
decimals = 2
|
||||
decimals = 7
|
||||
max_value = sys.float_info.max
|
||||
self._min_widget = DlgRef_1Spin_QTD('Tol Min', 0, decimals, max_value)
|
||||
self._max_widget = DlgRef_1Spin_QTD('Tol Max', 1000, decimals, max_value)
|
||||
self._min_widget = DlgRef_1Spin_QTD('Tol Min', 0.001, 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._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
|
||||
import GEOM
|
||||
|
||||
|
||||
salome.salome_init()
|
||||
geompy = geomBuilder.New()
|
||||
|
||||
@ -53,9 +52,7 @@ def run(args_dict, progress_emitter):
|
||||
sleep(1)
|
||||
|
||||
if ('source_solid' not in args_dict or
|
||||
'selected_ids' 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_max' not in args_dict or
|
||||
'Debug' not in args_dict):
|
||||
@ -64,45 +61,28 @@ def run(args_dict, progress_emitter):
|
||||
return False
|
||||
|
||||
source_solid = args_dict['source_solid']
|
||||
selected_ids = args_dict['selected_ids']
|
||||
result_name = args_dict['result_name']
|
||||
selection_level = args_dict['selection_level']
|
||||
Tol_min = args_dict['Tol_min']
|
||||
Tol_max = args_dict['Tol_max']
|
||||
minTol = args_dict['Tol_min']
|
||||
maxTol = args_dict['Tol_max']
|
||||
Debug = args_dict['Debug']
|
||||
|
||||
# Replace the lines below with an actual algorithm
|
||||
logging.info('Received arguments:')
|
||||
logging.info('\tsource_solid: %s', source_solid)
|
||||
logging.info('\tselected_ids: %s', selected_ids)
|
||||
logging.info('\tresult_name: %s', result_name)
|
||||
logging.info('\tselection_level: %s', selection_level)
|
||||
logging.info('\Tol_min: %s', Tol_min)
|
||||
logging.info('\Tol_max: %s', Tol_max)
|
||||
logging.info('\Tol_min: %s', minTol)
|
||||
logging.info('\Tol_max: %s', maxTol)
|
||||
logging.info('\Debug: %s', Debug)
|
||||
|
||||
progress_emitter.emit()
|
||||
sleep(1)
|
||||
|
||||
# Make a group
|
||||
# geomBuilder uses their own types - geomBuilder.ShapeType
|
||||
geom_builder_types = { GEOM.EDGE : 'EDGE', GEOM.FACE : 'FACE', GEOM.SOLID : 'SOLID' }
|
||||
type_str = geom_builder_types[selection_level]
|
||||
shape_type = geompy.ShapeType[type_str]
|
||||
group = geompy.CreateGroup(source_solid, shape_type, theName = result_name)
|
||||
for i in range(5000):
|
||||
vertex = geompy.MakeVertex(0,0,0)
|
||||
logging.info('\I: %s', i)
|
||||
if not progress_emitter.emit():
|
||||
return False
|
||||
|
||||
logging.info('Step1.')
|
||||
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
|
||||
return vertex
|
||||
|
||||
|
||||
def test():
|
||||
|
Loading…
Reference in New Issue
Block a user