import logging from PySide6.QtCore import Qt, QThreadPool, Signal, Slot, QSize from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QSizePolicy, QSpacerItem, QProgressDialog, QFileDialog from fixtracks.utils.converter import Converter class Json2PandasConverter(QWidget): back = Signal() def __init__(self, parent=None): super().__init__(parent) self._infile = None self._outfile = None self._converter = None self._progressDialog = None self.threadpool = QThreadPool() self._convertBtn = QPushButton("Convert") self._convertBtn.setEnabled(False) self._convertBtn.setToolTip("Convert data to pandas DataFrame") self._convertBtn.clicked.connect(self.on_convert) self._backBtn = QPushButton("Back") self._backBtn.clicked.connect(self.on_back) btnBox = QHBoxLayout() btnBox.setAlignment(Qt.AlignmentFlag.AlignLeft) btnBox.addWidget(self._backBtn) btnBox.addItem(QSpacerItem(100, 10, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)) btnBox.addWidget(self._convertBtn) layout = QVBoxLayout() layout.setAlignment(Qt.AlignmentFlag.AlignVCenter) layout.addWidget(QLabel("Convert JSON to Pandas dataframe")) layout.addLayout(self.layout_controls()) layout.addLayout(btnBox) self.setLayout(layout) def layout_controls(self): lyt = QHBoxLayout() inputBtn = QPushButton("input") inputBtn.setMinimumSize(QSize(100, 100)) inputBtn.clicked.connect(self.on_inputSelect) outputBtn = QPushButton("output") outputBtn.setMinimumSize(QSize(100, 100)) outputBtn.clicked.connect(self.on_outputSelect) lyt.addWidget(inputBtn) lyt.addWidget(outputBtn) return lyt def check_buttons(self): if self._infile is not None and self._outfile is not None: self._convertBtn.setEnabled(True) def on_convert(self): logging.info("Converting started") if self._converter is not None: self._converter = None self._converter = Converter(self._infile, self._outfile) self._progressDialog = QProgressDialog(parent=self) self._progressDialog.setAutoClose(True) self._progressDialog.setRange(0, 100) self._progressDialog.setLabelText("Converting pose data (will take a while, be patient):") self._progressDialog.setCancelButtonText("Cancel") self._progressDialog.setWindowModality(Qt.WindowModality.WindowModal) self._progressDialog.canceled.connect(self.on_convertCancelled) self._progressDialog.show() self._converter.signals.progress.connect(self.on_convertProgress) self._converter.signals.finished.connect(self.on_convertDone) self.threadpool.start(self._converter) @Slot(float) def on_convertProgress(self, value): logging.debug(f"Conversion progress: {value * 100}%") if self._progressDialog is not None: self._progressDialog.setValue(int(value * 100)) @Slot() def on_convertCancelled(self): logging.info("Cancel Button pressed! Requesting stop of converter") self._converter.stop_request() def on_back(self): logging.debug("Back button pressed!") self._infile = None self._outfile = None self._convertBtn.setEnabled(False) self.back.emit() def on_inputSelect(self): file_dialog = QFileDialog(self, "Select JSON File", "", "JSON Files (*.json);;All Files (*)") if file_dialog.exec(): self._infile = file_dialog.selectedFiles()[0] else: self._infile = None self.check_buttons() def on_outputSelect(self): file_dialog = QFileDialog(self, "Select CSV File", "", "CSV Files (*.csv);;All Files (*)") file_dialog.setAcceptMode(QFileDialog.AcceptSave) if file_dialog.exec(): file_path = file_dialog.selectedFiles()[0] if not file_path.endswith(".csv"): file_path += ".csv" self._outfile = file_path else: self._outfile = None self.check_buttons() @Slot(bool) def on_convertDone(self, state): logging.debug("Conversion stopped with status %s", state)