Newer
Older
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QFileDialog, QWidget
from utils.settings.SettingManager import SettingManager
from utils.graph2D.visplot_render import cross_section, render2D
from utils.graph3D.visplot_render import render3D
from utils.gui.pyqt.main_window.UI_MainWindow import Ui_MainWindow
from utils.gui.pyqt.main_window.Workers.DiscreteDataWorker import DiscreteDataProcessWorker
from utils.gui.pyqt.main_window.Workers.PreProcessWorker import PreProcessWorker
from utils.gui.pyqt.main_window.Workers.RawDataWorker import RawDataProcessWorker
from utils.gui.pyqt.error_popup.ErrorPopup import ErrorPopup
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
"""
Main window of the application
"""
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# Retrieve the UI
self.setupUi(self)
# Setup buttons listeners
self.start_analyse_button.clicked.connect(self.start_preprocess)
self.input_file_choose_btn.clicked.connect(self.select_file)
self.output_folder_choose_btn.clicked.connect(self.select_folder)
self.show_graph_checkbox.stateChanged.connect(self.toggle_graphs)
self.actionSauvegarder_le_model_redress.triggered.connect(self.save_model)
self.actionPr_f_rennces.triggered.connect(self.show_settings)
"Coupe XZ",
"Coupe YZ",
"Evolution du rayon moyen",
]
self.obj = None
self.raw_data= None
self.discrete_data = None
self.total = 2
self.comboBoxes = [
self.slot0ComboBox,
self.slot1ComboBox,
self.slot2ComboBox,
self.slot3ComboBox,
self.slot4ComboBox,
self.slot5ComboBox,
self.slot6ComboBox,
self.slot7ComboBox,
self.slot8ComboBox,
self.slot9ComboBox,
self.slot10ComboBox
]
for cb in self.comboBoxes:
cb.addItems(self.graphType)
self.slots = [
[self.slot0,"Aucun"],
[self.slot1,"Aucun"],
[self.slot2,"Aucun"],
[self.slot3,"Aucun"],
[self.slot4,"Aucun"],
[self.slot5,"Aucun"],
[self.slot6,"Aucun"],
[self.slot7,"Aucun"],
[self.slot8,"Aucun"],
[self.slot9,"Aucun"],
[self.slot10,"Aucun"]
for slot_nb,slot in enumerate(self.slots):
slot[1] = SettingManager.get_instance().get_last_graph(slot_nb)
self.comboBoxes[slot_nb].setCurrentText(slot[1])
###############################################################################
# #
# #
# Input/Setting Management #
# #
# #
###############################################################################
def select_file(self):
"""
Open a file dialog to select the input file
"""
file = QFileDialog.getOpenFileName()[0]
self.input_file_path.setPlainText(file)
self.output_file_prefix.setText(os.path.splitext(os.path.basename(file))[0])
def select_folder(self):
"""
Open a file dialog to select the output folder
"""
self.output_folder_path.setPlainText(QFileDialog.getExistingDirectory())
def check_input_file(self):
"""
Check if the input file is valid
"""
if not os.path.isfile(self.input_file_path.toPlainText()):
ErrorPopup("Fichier d'entrée invalide",button_label="Choisir un fichier d'entrée",button_callback=self.select_file).show_popup()
return False
return True
def check_output_folder(self):
"""
Check if the output folder is valid
"""
if not os.path.isdir(self.output_folder_path.toPlainText()):
ErrorPopup("Dossier de sortie invalide",button_label="Choisir un dossier de sortie",button_callback=self.select_folder).show_popup()
return False
return True
###############################################################################
# #
# #
# Data Processing #
# #
# #
###############################################################################
def start_preprocess(self):
"""
Start the analyse
"""
if not self.check_input_file():
return
if not self.check_output_folder():
return
settings = SettingManager.get_instance()
for count,_ in enumerate(self.slots):
self.slots[count][1] = self.comboBoxes[count].currentText()
settings.set_last_graph(count,self.slots[count][1])
self.preprocess_thread = QThread()
self.preprocess_worker = PreProcessWorker("PreProcessWorker",self.input_file_path.toPlainText())
self.preprocess_worker.moveToThread(self.preprocess_thread)
self.preprocess_thread.started.connect(self.preprocess_worker.run)
self.preprocess_worker.status.connect(self.set_status)
self.preprocess_worker.progress.connect(self.update_progress_bar)
self.preprocess_worker.processed_obj.connect(self.set_obj)
self.preprocess_worker.processed_obj.connect(self.process_raw_data)
self.preprocess_worker.processed_obj.connect(self.process_discrete_data)
self.preprocess_worker.finished.connect(self.preprocess_thread.quit)
self.preprocess_worker.finished.connect(self.preprocess_worker.deleteLater)
self.preprocess_thread.finished.connect(self.preprocess_thread.deleteLater)
def process_raw_data(self, obj:ScannedObject):
self.processrawdata_thread = QThread()
self.processraw_worker = RawDataProcessWorker("RawDataProcessWorker",
obj,
self.output_folder_path.toPlainText(),
self.output_file_prefix.text(),
self.discretisation_value_selector.value())
self.processraw_worker.moveToThread(self.processrawdata_thread)
# Connect the signals
# Start
self.processrawdata_thread.started.connect(self.processraw_worker.run)
# Progress
self.processraw_worker.status.connect(self.set_status)
self.processraw_worker.progress.connect(self.update_progress_bar)
self.processraw_worker.processedData.connect(self.set_raw_data)
# Finished
self.processraw_worker.finished.connect(self.finish_analyse)
self.processraw_worker.finished.connect(self.processrawdata_thread.quit)
self.processraw_worker.finished.connect(self.processraw_worker.deleteLater)
self.processrawdata_thread.finished.connect(self.processrawdata_thread.deleteLater)
# Start the thread
self.processrawdata_thread.start()
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
def process_discrete_data(self, obj:ScannedObject):
self.processdiscrete_thread = QThread()
self.processdiscrete_worker = DiscreteDataProcessWorker("DiscreteDataProcessWorker",
obj,
self.output_folder_path.toPlainText(),
self.output_file_prefix.text(),
self.discretisation_value_selector.value())
self.processdiscrete_worker.moveToThread(self.processdiscrete_thread)
# Connect the signals
# Start
self.processdiscrete_thread.started.connect(self.processdiscrete_worker.run)
# Progress
self.processdiscrete_worker.status.connect(self.set_status)
self.processdiscrete_worker.progress.connect(self.update_progress_bar)
self.processdiscrete_worker.processedData.connect(self.set_discrete_data)
# Finished
self.processdiscrete_worker.finished.connect(self.finish_analyse)
self.processdiscrete_worker.finished.connect(self.processdiscrete_thread.quit)
self.processdiscrete_worker.finished.connect(self.processdiscrete_worker.deleteLater)
self.processdiscrete_thread.finished.connect(self.processdiscrete_thread.deleteLater)
# Start the thread
self.processdiscrete_thread.start()
def set_obj(self,obj:ScannedObject):
self.obj = obj
def set_discrete_data(self,discrete_data:dict):
self.discrete_data = discrete_data
def set_raw_data(self,raw_data:dict):
self.raw_data = raw_data
def save_model(self):
if self.obj is None:
ErrorPopup("Aucune analyse effectuée. Aucun modèle à sauvegarder").show_popup()
return
file_path = QFileDialog.getSaveFileName(self,
"Sauvegarder le modèle",
"./",
"Fichier OBJ (*.obj)")
self.obj.export_obj(file_path[0])
###############################################################################
# #
# #
# Graphs management #
# #
# #
###############################################################################
def toggle_graphs(self):
if self.show_graph_checkbox.isChecked():
self.Graphs.show()
else:
self.Graphs.hide()
def renderGraphs(self,obj:ScannedObject,raw_data:dict,discrete_data:dict):
if not self.show_graph_checkbox.isChecked():
for slot in self.slots:
current_slot = slot[0]
graph_type = slot[1]
if graph_type == "Mesh3D":
current_slot.addWidget(render3D(obj,False).native)
current_slot.addWidget(cross_section(obj.get_x(),
obj.get_z(),
"Coupe XZ",
"X (en mm)",
"Z (en mm)",
False).native)
current_slot.addWidget(cross_section(obj.get_y(),
obj.get_z(),
"Coupe YZ",
"Y (en mm)",
"Z (en mm)",
False).native)
current_slot.addWidget(render2D(list(zip(discrete_data['Z moy (en mm)'],discrete_data['Rayon moyen (en mm)'])),
"Evolution du rayon moyen en fonction de Z",
"Z (en mm)",
"Rayon moyen (en mm)\n",
False).native)
if not self.show_graph_checkbox.isChecked():
return
for slot,_ in self.slots:
for i in reversed(range(slot.count())):
slot.itemAt(i).widget().setParent(None)
###############################################################################
# #
# #
# User interface updates #
# #
# #
###############################################################################
self.completed += 1
if self.completed == self.total:
self.status_text.setText("Done")
self.analyse_progress_bar.setValue(100)
self.renderGraphs(self.obj,self.raw_data,self.discrete_data)
self.start_analyse_button.setEnabled(True)
def update_progress_bar(self, value):
"""
Update the progress bar
"""
self.analyse_progress_bar.setValue(value)
def set_status(self, status:str):
"""
Set the status of the analyse
"""
self.status_text.setText(status)
def show_settings(self):
"""
Show the settings window
"""
self.settings_window.show()