def __init__(self, compare_frame_controller: CompareFrameController, generator_tab_controller: GeneratorTabController, project_manager: ProjectManager, parent): super().__init__(parent) self.project_manager = project_manager self.compare_frame_controller = compare_frame_controller self.generator_tab_controller = generator_tab_controller self.proto_analyzer = compare_frame_controller.proto_analyzer self.simulator_config = SimulatorConfiguration(self.project_manager) self.sim_expression_parser = SimulatorExpressionParser( self.simulator_config) SimulatorItem.simulator_config = self.simulator_config SimulatorItem.expression_parser = self.sim_expression_parser self.ui = Ui_SimulatorTab() self.ui.setupUi(self) util.set_splitter_stylesheet(self.ui.splitter) util.set_splitter_stylesheet(self.ui.splitterLeftRight) self.ui.splitter.setSizes([self.width() / 0.7, self.width() / 0.3]) self.ui.treeProtocols.setHeaderHidden(True) self.tree_model = self.generator_tab_controller.tree_model self.ui.treeProtocols.setModel(self.tree_model) self.participant_table_model = ParticipantTableModel( project_manager.participants) self.ui.tableViewParticipants.setModel(self.participant_table_model) self.participant_table_model.update() self.simulator_message_field_model = SimulatorMessageFieldModel(self) self.ui.tblViewFieldValues.setModel(self.simulator_message_field_model) self.ui.tblViewFieldValues.setItemDelegateForColumn( 1, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn( 2, ComboBoxDelegate(SimulatorProtocolLabel.VALUE_TYPES, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn( 3, ProtocolValueDelegate(controller=self, parent=self.ui.tblViewFieldValues)) self.project_manager.reload_field_types() self.update_field_name_column() self.simulator_message_table_model = SimulatorMessageTableModel( self.project_manager, self) self.ui.tblViewMessage.setModel(self.simulator_message_table_model) self.ui.ruleCondLineEdit.setValidator( RuleExpressionValidator(self.sim_expression_parser, is_formula=False)) self.completer_model = QStringListModel([]) self.ui.ruleCondLineEdit.setCompleter( QCompleter(self.completer_model, self.ui.ruleCondLineEdit)) self.ui.ruleCondLineEdit.setToolTip( self.sim_expression_parser.rule_condition_help) self.simulator_scene = SimulatorScene( mode=0, simulator_config=self.simulator_config) self.simulator_scene.tree_root_item = compare_frame_controller.proto_tree_model.rootItem self.ui.gvSimulator.setScene(self.simulator_scene) self.ui.gvSimulator.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.ui.gvSimulator.proto_analyzer = compare_frame_controller.proto_analyzer self.__active_item = None self.ui.listViewSimulate.setModel( SimulatorParticipantListModel(self.simulator_config)) self.ui.spinBoxNRepeat.setValue( self.project_manager.simulator_num_repeat) self.ui.spinBoxTimeout.setValue( self.project_manager.simulator_timeout_ms) self.ui.spinBoxRetries.setValue(self.project_manager.simulator_retries) self.ui.comboBoxError.setCurrentIndex( self.project_manager.simulator_error_handling_index) # place save/load button at corner of tab widget frame = QFrame(parent=self) frame.setLayout(QHBoxLayout()) frame.setFrameStyle(frame.NoFrame) self.ui.btnSave = QToolButton(self.ui.tab) self.ui.btnSave.setIcon(QIcon.fromTheme("document-save")) frame.layout().addWidget(self.ui.btnSave) self.ui.btnLoad = QToolButton(self.ui.tab) self.ui.btnLoad.setIcon(QIcon.fromTheme("document-open")) frame.layout().addWidget(self.ui.btnLoad) frame.layout().setContentsMargins(0, 0, 0, 0) self.ui.tabWidget.setCornerWidget(frame) self.ui.splitterLeftRight.setSizes( [0.2 * self.width(), 0.8 * self.width()]) self.create_connects()
def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, signals: list = None, signal_tree_model=None, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.simulator_config = simulator_config # type: SimulatorConfiguration self.rx_needed = self.simulator_config.rx_needed self.tx_needed = self.simulator_config.tx_needed self.current_transcript_index = 0 self.simulator_scene = SimulatorScene(mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() if self.rx_needed: self.device_settings_rx_widget = DeviceSettingsWidget(project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget(self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, network_raw_mode=True, signals=signals) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(1, self.sniff_settings_widget) sniffer = self.sniff_settings_widget.sniffer self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.device_settings_rx_widget = self.sniff_settings_widget = self.scene_manager = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, False) self.ui.graphicsViewPreview.hide() self.ui.btnSaveRX.hide() self.ui.checkBoxCaptureFullRX.hide() sniffer = None if self.tx_needed: self.device_settings_tx_widget = DeviceSettingsWidget(project_manager, is_tx=True, backend_handler=self.backend_handler, continuous_send_mode=True) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, signal_tree_model=signal_tree_model, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() sender = EndlessSender(self.backend_handler, send_device) else: self.device_settings_tx_widget = self.modulation_settings_widget = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, False) sender = None self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=sniffer, sender=sender) if self.device_settings_tx_widget: self.device_settings_tx_widget.device = self.simulator.sender.device self.update_buttons() self.create_connects() if self.device_settings_rx_widget: self.device_settings_rx_widget.bootstrap(project_manager.simulator_rx_conf) if self.device_settings_tx_widget: self.device_settings_tx_widget.bootstrap(project_manager.simulator_tx_conf) self.ui.textEditTranscript.setFont(util.get_monospace_font()) if constants.SETTINGS.value('default_view', 0, int) == 1: self.ui.radioButtonTranscriptHex.setChecked(True)
class SimulatorTabController(QWidget): open_in_analysis_requested = pyqtSignal(str) rx_file_saved = pyqtSignal(str) def __init__(self, compare_frame_controller: CompareFrameController, generator_tab_controller: GeneratorTabController, project_manager: ProjectManager, parent): super().__init__(parent) self.project_manager = project_manager self.compare_frame_controller = compare_frame_controller self.generator_tab_controller = generator_tab_controller self.proto_analyzer = compare_frame_controller.proto_analyzer self.simulator_config = SimulatorConfiguration(self.project_manager) self.sim_expression_parser = SimulatorExpressionParser( self.simulator_config) SimulatorItem.simulator_config = self.simulator_config SimulatorItem.expression_parser = self.sim_expression_parser self.ui = Ui_SimulatorTab() self.ui.setupUi(self) util.set_splitter_stylesheet(self.ui.splitter) util.set_splitter_stylesheet(self.ui.splitterLeftRight) self.ui.splitter.setSizes([self.width() / 0.7, self.width() / 0.3]) self.ui.treeProtocols.setHeaderHidden(True) self.tree_model = self.generator_tab_controller.tree_model self.ui.treeProtocols.setModel(self.tree_model) self.participant_table_model = ParticipantTableModel( project_manager.participants) self.ui.tableViewParticipants.setModel(self.participant_table_model) self.participant_table_model.update() self.simulator_message_field_model = SimulatorMessageFieldModel(self) self.ui.tblViewFieldValues.setModel(self.simulator_message_field_model) self.ui.tblViewFieldValues.setItemDelegateForColumn( 1, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn( 2, ComboBoxDelegate(SimulatorProtocolLabel.VALUE_TYPES, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn( 3, ProtocolValueDelegate(controller=self, parent=self.ui.tblViewFieldValues)) self.project_manager.reload_field_types() self.update_field_name_column() self.simulator_message_table_model = SimulatorMessageTableModel( self.project_manager, self) self.ui.tblViewMessage.setModel(self.simulator_message_table_model) self.ui.ruleCondLineEdit.setValidator( RuleExpressionValidator(self.sim_expression_parser, is_formula=False)) self.completer_model = QStringListModel([]) self.ui.ruleCondLineEdit.setCompleter( QCompleter(self.completer_model, self.ui.ruleCondLineEdit)) self.ui.ruleCondLineEdit.setToolTip( self.sim_expression_parser.rule_condition_help) self.simulator_scene = SimulatorScene( mode=0, simulator_config=self.simulator_config) self.simulator_scene.tree_root_item = compare_frame_controller.proto_tree_model.rootItem self.ui.gvSimulator.setScene(self.simulator_scene) self.ui.gvSimulator.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.ui.gvSimulator.proto_analyzer = compare_frame_controller.proto_analyzer self.__active_item = None self.ui.listViewSimulate.setModel( SimulatorParticipantListModel(self.simulator_config)) self.ui.spinBoxNRepeat.setValue( self.project_manager.simulator_num_repeat) self.ui.spinBoxTimeout.setValue( self.project_manager.simulator_timeout_ms) self.ui.spinBoxRetries.setValue(self.project_manager.simulator_retries) self.ui.comboBoxError.setCurrentIndex( self.project_manager.simulator_error_handling_index) # place save/load button at corner of tab widget frame = QFrame(parent=self) frame.setLayout(QHBoxLayout()) frame.setFrameStyle(frame.NoFrame) self.ui.btnSave = QToolButton(self.ui.tab) self.ui.btnSave.setIcon(QIcon.fromTheme("document-save")) frame.layout().addWidget(self.ui.btnSave) self.ui.btnLoad = QToolButton(self.ui.tab) self.ui.btnLoad.setIcon(QIcon.fromTheme("document-open")) frame.layout().addWidget(self.ui.btnLoad) frame.layout().setContentsMargins(0, 0, 0, 0) self.ui.tabWidget.setCornerWidget(frame) self.ui.splitterLeftRight.setSizes( [0.2 * self.width(), 0.8 * self.width()]) self.create_connects() def refresh_field_types_for_labels(self): for msg in self.simulator_config.get_all_messages(): for lbl in (lbl for lbl in msg.message_type if lbl.field_type is not None): msg.message_type.change_field_type_of_label( lbl, self.field_types_by_caption.get(lbl.field_type.caption, None)) self.update_field_name_column() self.update_ui() @property def field_types(self): return self.project_manager.field_types @property def field_types_by_caption(self): return self.project_manager.field_types_by_caption def update_field_name_column(self): field_types = [ft.caption for ft in self.field_types] self.ui.tblViewFieldValues.setItemDelegateForColumn( 0, ComboBoxDelegate(field_types, is_editable=True, return_index=False, parent=self.ui.tblViewFieldValues)) def create_connects(self): self.ui.btnChooseCommand.clicked.connect( self.on_btn_choose_command_clicked) self.ui.lineEditTriggerCommand.textChanged.connect( self.on_line_edit_trigger_command_text_changed) self.ui.checkBoxPassTranscriptSTDIN.clicked.connect( self.on_check_box_pass_transcript_STDIN_clicked) self.ui.doubleSpinBoxSleep.editingFinished.connect( self.on_spinbox_sleep_editing_finished) self.ui.ruleCondLineEdit.textChanged.connect( self.on_rule_cond_line_edit_text_changed) self.ui.btnStartSim.clicked.connect(self.on_btn_simulate_clicked) self.ui.goto_combobox.currentIndexChanged.connect( self.on_goto_combobox_index_changed) self.ui.spinBoxRepeat.valueChanged.connect( self.on_repeat_value_changed) self.ui.cbViewType.currentIndexChanged.connect( self.on_view_type_changed) self.ui.tblViewMessage.create_label_triggered.connect( self.create_simulator_label) self.ui.tblViewMessage.open_modulator_dialog_clicked.connect( self.open_modulator_dialog) self.ui.tblViewMessage.selectionModel().selectionChanged.connect( self.on_table_selection_changed) self.ui.tabWidget.currentChanged.connect(self.on_selected_tab_changed) self.ui.btnSave.clicked.connect(self.on_btn_save_clicked) self.ui.btnLoad.clicked.connect(self.on_btn_load_clicked) self.ui.listViewSimulate.model().participant_simulate_changed.connect( self.on_participant_simulate_changed) self.ui.btnAddParticipant.clicked.connect( self.ui.tableViewParticipants.on_add_action_triggered) self.ui.btnRemoveParticipant.clicked.connect( self.ui.tableViewParticipants.on_remove_action_triggered) self.ui.btnUp.clicked.connect( self.ui.tableViewParticipants.on_move_up_action_triggered) self.ui.btnDown.clicked.connect( self.ui.tableViewParticipants.on_move_down_action_triggered) self.participant_table_model.participant_edited.connect( self.on_participant_edited) self.tree_model.modelReset.connect(self.refresh_tree) self.simulator_scene.selectionChanged.connect( self.on_simulator_scene_selection_changed) self.simulator_scene.files_dropped.connect(self.on_files_dropped) self.simulator_message_field_model.protocol_label_updated.connect( self.item_updated) self.ui.gvSimulator.message_updated.connect(self.item_updated) self.ui.gvSimulator.consolidate_messages_clicked.connect( self.consolidate_messages) self.simulator_config.items_added.connect(self.refresh_message_table) self.simulator_config.items_updated.connect(self.refresh_message_table) self.simulator_config.items_moved.connect(self.refresh_message_table) self.simulator_config.items_deleted.connect(self.refresh_message_table) self.simulator_config.participants_changed.connect( self.on_participants_changed) self.simulator_config.item_dict_updated.connect( self.on_item_dict_updated) self.simulator_config.active_participants_updated.connect( self.on_active_participants_updated) self.ui.gvSimulator.message_updated.connect( self.on_message_source_or_destination_updated) self.ui.spinBoxNRepeat.valueChanged.connect( self.on_spinbox_num_repeat_value_changed) self.ui.spinBoxTimeout.valueChanged.connect( self.on_spinbox_timeout_value_changed) self.ui.comboBoxError.currentIndexChanged.connect( self.on_combobox_error_handling_index_changed) self.ui.spinBoxRetries.valueChanged.connect( self.on_spinbox_retries_value_changed) self.ui.tblViewFieldValues.item_link_clicked.connect( self.on_table_item_link_clicked) self.ui.tblViewMessage.edit_label_triggered.connect( self.on_edit_label_triggered) self.ui.spinBoxCounterStart.editingFinished.connect( self.on_spinbox_counter_start_editing_finished) self.ui.spinBoxCounterStep.editingFinished.connect( self.on_spinbox_counter_step_editing_finished) def consolidate_messages(self): self.simulator_config.consolidate_messages() def on_repeat_value_changed(self, value): self.active_item.repeat = value self.simulator_config.items_updated.emit([self.active_item]) def on_item_dict_updated(self): self.completer_model.setStringList( self.sim_expression_parser.get_identifiers()) def on_selected_tab_changed(self, index: int): if index == 0: if self.active_item is not None: self.ui.gvSimulator.jump_to_item(self.active_item) else: self.update_ui() else: self.ui.tblViewMessage.resize_columns() self.update_vertical_table_header() def refresh_message_table(self): self.simulator_message_table_model.protocol.messages[:] = self.simulator_config.get_all_messages( ) self.simulator_message_table_model.update() if isinstance(self.active_item, SimulatorMessage): self.simulator_message_field_model.update() self.ui.tblViewMessage.resize_columns() self.update_ui() def load_config_from_xml_tag(self, xml_tag, update_before=True): if xml_tag is None: return if update_before: self.simulator_config.on_project_updated() self.simulator_config.load_from_xml(xml_tag, self.proto_analyzer.message_types) self.project_manager.project_updated.emit() def load_simulator_file(self, filename: str): try: tree = ET.parse(filename) self.load_config_from_xml_tag(tree.getroot(), update_before=False) except Exception as e: logger.exception(e) def save_simulator_file(self, filename: str): tag = self.simulator_config.save_to_xml(standalone=True) util.write_xml_to_file(tag, filename) def close_all(self): self.simulator_scene.clear_all() @pyqtSlot(int, int, int) def create_simulator_label(self, msg_index: int, start: int, end: int): con = self.simulator_message_table_model.protocol start, end = con.convert_range(start, end - 1, self.ui.cbViewType.currentIndex(), 0, False, msg_index) lbl = self.simulator_config.add_label( start=start, end=end, parent_item=con.messages[msg_index]) try: index = self.simulator_message_field_model.message_type.index(lbl) self.ui.tblViewFieldValues.edit( self.simulator_message_field_model.createIndex(index, 0)) except ValueError: pass @pyqtSlot() def open_modulator_dialog(self): selected_message = self.simulator_message_table_model.protocol.messages[ self.ui.tblViewMessage.selected_rows[0]] preselected_index = selected_message.modulator_index modulator_dialog = ModulatorDialog(self.project_manager.modulators, tree_model=self.tree_model, parent=self) modulator_dialog.ui.comboBoxCustomModulations.setCurrentIndex( preselected_index) modulator_dialog.showMaximized() modulator_dialog.initialize(selected_message.encoded_bits_str[0:10]) modulator_dialog.finished.connect(self.refresh_modulators) modulator_dialog.finished.connect( self.generator_tab_controller.refresh_pause_list) @pyqtSlot() def refresh_modulators(self): # update Generator tab ... cBoxModulations = self.generator_tab_controller.ui.cBoxModulations current_index = cBoxModulations.currentIndex() cBoxModulations.clear() for modulator in self.project_manager.modulators: cBoxModulations.addItem(modulator.name) cBoxModulations.setCurrentIndex(current_index) # update Simulator tab ... index = self.sender().ui.comboBoxCustomModulations.currentIndex() for row in self.ui.tblViewMessage.selected_rows: self.simulator_message_table_model.protocol.messages[ row].modulator_index = index def update_goto_combobox(self, active_item: SimulatorGotoAction): assert isinstance(active_item, SimulatorGotoAction) goto_combobox = self.ui.goto_combobox goto_combobox.blockSignals(True) goto_combobox.clear() goto_combobox.addItem("Select item ...") goto_combobox.addItems(active_item.get_valid_goto_targets()) goto_combobox.setCurrentIndex(-1) goto_combobox.blockSignals(False) index = goto_combobox.findText(self.active_item.goto_target) if index == -1: index = 0 goto_combobox.setCurrentIndex(index) def update_ui(self): if self.active_item is not None: text = self.tr("Detail view for item #") + self.active_item.index() if isinstance(self.active_item, SimulatorMessage): text += " (" + self.active_item.message_type.name + ")" self.ui.spinBoxRepeat.setValue(self.active_item.repeat) self.ui.lblEncodingDecoding.setText( self.active_item.decoder.name) self.ui.lblMsgFieldsValues.setText(text) else: self.ui.lblMsgFieldsValues.setText(self.tr("Detail view for item")) def update_vertical_table_header(self): self.simulator_message_table_model.refresh_vertical_header() self.ui.tblViewMessage.resize_vertical_header() @pyqtSlot() def on_rule_cond_line_edit_text_changed(self): self.active_item.condition = self.ui.ruleCondLineEdit.text() self.item_updated(self.active_item) @pyqtSlot() def on_view_type_changed(self): self.simulator_message_table_model.proto_view = self.ui.cbViewType.currentIndex( ) self.simulator_message_table_model.update() self.ui.tblViewMessage.resize_columns() @pyqtSlot() def on_goto_combobox_index_changed(self): if not isinstance(self.active_item, SimulatorGotoAction): return self.active_item.goto_target = None if self.ui.goto_combobox.currentIndex( ) == 0 else self.ui.goto_combobox.currentText() self.item_updated(self.active_item) @pyqtSlot() def on_simulator_scene_selection_changed(self): selected_items = self.simulator_scene.selectedItems() self.active_item = selected_items[ 0].model_item if selected_items else None self.update_ui() @pyqtSlot() def on_table_selection_changed(self): selection = self.ui.tblViewMessage.selectionModel().selection() if selection.isEmpty(): self.active_item = None self.ui.lNumSelectedColumns.setText("0") else: max_row = numpy.max([rng.bottom() for rng in selection]) self.active_item = self.simulator_message_table_model.protocol.messages[ max_row] _, _, start, end = self.ui.tblViewMessage.selection_range() self.ui.lNumSelectedColumns.setText(str(end - start)) self.update_ui() @property def active_item(self): return self.__active_item @active_item.setter def active_item(self, value): self.__active_item = value if isinstance(self.active_item, SimulatorGotoAction): self.update_goto_combobox(self.active_item) self.ui.detail_view_widget.setCurrentIndex(1) elif isinstance(self.active_item, SimulatorMessage): self.simulator_message_field_model.update() self.ui.spinBoxRepeat.setValue(self.active_item.repeat) self.ui.lblEncodingDecoding.setText(self.active_item.decoder.name) self.ui.detail_view_widget.setCurrentIndex(2) elif (isinstance(self.active_item, SimulatorRuleCondition) and self.active_item.type != ConditionType.ELSE): self.ui.ruleCondLineEdit.setText(self.active_item.condition) self.ui.detail_view_widget.setCurrentIndex(3) elif isinstance(self.active_item, SimulatorTriggerCommandAction): self.ui.lineEditTriggerCommand.setText(self.active_item.command) self.ui.checkBoxPassTranscriptSTDIN.setChecked( self.active_item.pass_transcript) self.ui.detail_view_widget.setCurrentIndex(4) elif isinstance(self.active_item, SimulatorSleepAction): self.ui.doubleSpinBoxSleep.setValue(self.active_item.sleep_time) self.ui.detail_view_widget.setCurrentIndex(5) elif isinstance(self.active_item, SimulatorCounterAction): self.ui.spinBoxCounterStart.setValue(self.active_item.start) self.ui.spinBoxCounterStep.setValue(self.active_item.step) self.ui.detail_view_widget.setCurrentIndex(6) else: self.ui.detail_view_widget.setCurrentIndex(0) self.update_ui() @pyqtSlot() def on_btn_simulate_clicked(self): if not self.simulator_config.protocol_valid(): QMessageBox.critical( self, self.tr("Invalid protocol configuration"), self. tr("There are some problems with your protocol configuration. Please fix them first." )) return if not len(self.simulator_config.get_all_messages()): QMessageBox.critical(self, self.tr("No messages found"), self.tr("Please add at least one message.")) return num_simulated = len( [p for p in self.project_manager.participants if p.simulate]) if num_simulated == 0: if self.ui.listViewSimulate.model().rowCount() == 0: QMessageBox.critical( self, self.tr("No active participants"), self. tr("You have no active participants.<br>" "Please add a participant in the <i>Participants tab</i> and " "assign it to at least one message as <i>source</i> or <i>destination.</i>" )) return else: QMessageBox.critical( self, self.tr("No participant for simulation selected"), self.tr("Please check at least one participant from the " "<i>Simulate these participants</i> list.")) return try: self.get_simulator_dialog().exec_() except Exception as e: Errors.exception(e) def get_simulator_dialog(self) -> SimulatorDialog: protos = [ p for proto_list in self.tree_model.protocols.values() for p in proto_list ] signals = [p.signal for p in protos if p.signal is not None] s = SimulatorDialog(self.simulator_config, self.project_manager.modulators, self.sim_expression_parser, self.project_manager, signals=signals, signal_tree_model=self.tree_model, parent=self) s.rx_parameters_changed.connect( self.project_manager.on_simulator_rx_parameters_changed) s.sniff_parameters_changed.connect( self.project_manager.on_simulator_sniff_parameters_changed) s.tx_parameters_changed.connect( self.project_manager.on_simulator_tx_parameters_changed) s.open_in_analysis_requested.connect( self.open_in_analysis_requested.emit) s.rx_file_saved.connect(self.rx_file_saved.emit) return s @pyqtSlot() def on_btn_choose_command_clicked(self): file_name, ok = QFileDialog.getOpenFileName(self, self.tr("Choose program"), QDir.homePath()) if file_name is not None and ok: self.ui.lineEditTriggerCommand.setText(file_name) @pyqtSlot() def on_line_edit_trigger_command_text_changed(self): self.active_item.command = self.ui.lineEditTriggerCommand.text() self.item_updated(self.active_item) @pyqtSlot() def on_check_box_pass_transcript_STDIN_clicked(self): self.active_item.pass_transcript = self.ui.checkBoxPassTranscriptSTDIN.isChecked( ) self.item_updated(self.active_item) @pyqtSlot() def on_spinbox_counter_start_editing_finished(self): self.active_item.start = self.ui.spinBoxCounterStart.value() self.item_updated(self.active_item) @pyqtSlot() def on_spinbox_counter_step_editing_finished(self): self.active_item.step = self.ui.spinBoxCounterStep.value() self.item_updated(self.active_item) @pyqtSlot() def on_spinbox_sleep_editing_finished(self): self.active_item.sleep_time = self.ui.doubleSpinBoxSleep.value() self.item_updated(self.active_item) @pyqtSlot() def on_participants_changed(self): self.update_vertical_table_header() self.participant_table_model.update() self.ui.listViewSimulate.model().update() def item_updated(self, item: SimulatorItem): self.simulator_config.items_updated.emit([item]) @pyqtSlot() def refresh_tree(self): self.ui.treeProtocols.expandAll() @pyqtSlot() def on_btn_save_clicked(self): filename = FileOperator.get_save_file_name( initial_name="myprofile.sim.xml", caption="Save simulator profile") if filename: self.save_simulator_file(filename) @pyqtSlot() def on_btn_load_clicked(self): dialog = FileOperator.get_open_dialog(False, parent=self, name_filter="simulator") if dialog.exec_(): self.load_simulator_file(dialog.selectedFiles()[0]) @pyqtSlot() def on_participant_edited(self): self.project_manager.project_updated.emit() @pyqtSlot(int) def on_spinbox_num_repeat_value_changed(self, value): self.project_manager.simulator_num_repeat = value @pyqtSlot(int) def on_spinbox_timeout_value_changed(self, value): self.project_manager.simulator_timeout_ms = value @pyqtSlot(int) def on_spinbox_retries_value_changed(self, value): self.project_manager.simulator_retries = value @pyqtSlot(int) def on_combobox_error_handling_index_changed(self, index: int): self.project_manager.simulator_error_handling_index = index @pyqtSlot() def on_message_source_or_destination_updated(self): self.simulator_config.update_active_participants() @pyqtSlot(int, int) def on_table_item_link_clicked(self, row: int, column: int): try: lbl = self.simulator_message_field_model.message_type[ row] # type: SimulatorProtocolLabel assert lbl.is_checksum_label assert isinstance(self.active_item, SimulatorMessage) except (IndexError, AssertionError): return d = QDialog(parent=self) layout = QHBoxLayout() layout.addWidget( ChecksumWidget(lbl.label, self.active_item, self.ui.cbViewType.currentIndex())) d.setLayout(layout) d.show() @pyqtSlot(Participant) def on_participant_simulate_changed(self, participant: Participant): self.simulator_scene.refresh_participant(participant) @pyqtSlot() def on_active_participants_updated(self): self.ui.listViewSimulate.model().update() @pyqtSlot(int) def on_edit_label_triggered(self, label_index: int): view_type = self.ui.cbViewType.currentIndex() protocol_label_dialog = ProtocolLabelDialog( message=self.ui.tblViewMessage.selected_message, viewtype=view_type, selected_index=label_index, parent=self) protocol_label_dialog.finished.connect( self.on_protocol_label_dialog_finished) protocol_label_dialog.showMaximized() @pyqtSlot() def on_protocol_label_dialog_finished(self): self.simulator_message_field_model.update() self.simulator_message_table_model.update() self.update_ui() @pyqtSlot(list) def on_files_dropped(self, file_urls: list): for filename in (file_url.toLocalFile() for file_url in file_urls if file_url.isLocalFile()): self.load_simulator_file(filename)
def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.simulator_config = simulator_config self.simulator_scene = SimulatorScene( mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() self.device_settings_rx_widget = DeviceSettingsWidget( project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget( self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, real_time=True, network_raw_mode=True) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget( 0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget( 1, self.sniff_settings_widget) self.device_settings_tx_widget = DeviceSettingsWidget( project_manager, is_tx=True, backend_handler=self.backend_handler) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget( 0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget( 1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=self.sniff_settings_widget.sniffer, sender=EndlessSender( self.backend_handler, send_device)) self.device_settings_tx_widget.device = self.simulator.sender.device self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) self.update_buttons() self.create_connects() self.__bootstrap_device_settings(self.device_settings_rx_widget, project_manager.simulator_rx_conf) self.__bootstrap_sniff_settings(self.sniff_settings_widget, project_manager.simulator_rx_conf) self.__bootstrap_device_settings(self.device_settings_tx_widget, project_manager.simulator_tx_conf)
class SimulatorDialog(QDialog): rx_parameters_changed = pyqtSignal(dict) tx_parameters_changed = pyqtSignal(dict) sniff_parameters_changed = pyqtSignal(dict) open_in_analysis_requested = pyqtSignal(str) rx_file_saved = pyqtSignal(str) def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, signals: list = None, signal_tree_model=None, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.simulator_config = simulator_config # type: SimulatorConfiguration self.rx_needed = self.simulator_config.rx_needed self.tx_needed = self.simulator_config.tx_needed self.current_transcript_index = 0 self.simulator_scene = SimulatorScene(mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() if self.rx_needed: self.device_settings_rx_widget = DeviceSettingsWidget(project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget(self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, network_raw_mode=True, signals=signals) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(1, self.sniff_settings_widget) sniffer = self.sniff_settings_widget.sniffer self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.device_settings_rx_widget = self.sniff_settings_widget = self.scene_manager = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, False) self.ui.graphicsViewPreview.hide() self.ui.btnSaveRX.hide() self.ui.checkBoxCaptureFullRX.hide() sniffer = None if self.tx_needed: self.device_settings_tx_widget = DeviceSettingsWidget(project_manager, is_tx=True, backend_handler=self.backend_handler, continuous_send_mode=True) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, signal_tree_model=signal_tree_model, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() sender = EndlessSender(self.backend_handler, send_device) else: self.device_settings_tx_widget = self.modulation_settings_widget = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, False) sender = None self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=sniffer, sender=sender) if self.device_settings_tx_widget: self.device_settings_tx_widget.device = self.simulator.sender.device self.update_buttons() self.create_connects() if self.device_settings_rx_widget: self.device_settings_rx_widget.bootstrap(project_manager.simulator_rx_conf) if self.device_settings_tx_widget: self.device_settings_tx_widget.bootstrap(project_manager.simulator_tx_conf) self.ui.textEditTranscript.setFont(util.get_monospace_font()) if constants.SETTINGS.value('default_view', 0, int) == 1: self.ui.radioButtonTranscriptHex.setChecked(True) def create_connects(self): if self.rx_needed: self.device_settings_rx_widget.selected_device_changed.connect(self.on_selected_rx_device_changed) self.device_settings_rx_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) self.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) self.ui.btnSaveRX.clicked.connect(self.on_btn_save_rx_clicked) self.ui.checkBoxCaptureFullRX.clicked.connect(self.on_checkbox_capture_full_rx_clicked) self.ui.btnTestSniffSettings.clicked.connect(self.on_btn_test_sniff_settings_clicked) self.ui.btnOpenInAnalysis.clicked.connect(self.on_btn_open_in_analysis_clicked) if self.tx_needed: self.device_settings_tx_widget.selected_device_changed.connect(self.on_selected_tx_device_changed) self.device_settings_tx_widget.device_parameters_changed.connect(self.tx_parameters_changed.emit) self.ui.radioButtonTranscriptBit.clicked.connect(self.on_radio_button_transcript_bit_clicked) self.ui.radioButtonTranscriptHex.clicked.connect(self.on_radio_button_transcript_hex_clicked) self.simulator_scene.selectionChanged.connect(self.update_buttons) self.simulator_config.items_updated.connect(self.update_buttons) self.ui.btnLogAll.clicked.connect(self.on_btn_log_all_clicked) self.ui.btnLogNone.clicked.connect(self.on_btn_log_none_clicked) self.ui.btnToggleLog.clicked.connect(self.on_btn_toggle_clicked) self.ui.btnStartStop.clicked.connect(self.on_btn_start_stop_clicked) self.ui.btnSaveLog.clicked.connect(self.on_btn_save_log_clicked) self.ui.btnSaveTranscript.clicked.connect(self.on_btn_save_transcript_clicked) self.timer.timeout.connect(self.on_timer_timeout) self.simulator.simulation_started.connect(self.on_simulation_started) self.simulator.simulation_stopped.connect(self.on_simulation_stopped) def update_buttons(self): selectable_items = self.simulator_scene.selectable_items() all_items_selected = all(item.model_item.logging_active for item in selectable_items) any_item_selected = any(item.model_item.logging_active for item in selectable_items) self.ui.btnToggleLog.setEnabled(len(self.simulator_scene.selectedItems())) self.ui.btnLogAll.setEnabled(not all_items_selected) self.ui.btnLogNone.setEnabled(any_item_selected) def __get_full_transcript(self) -> list: return self.simulator.transcript.get_for_all_participants(all_rounds=True, use_bit=self.ui.radioButtonTranscriptBit.isChecked()) def update_view(self): for device_message in filter(None, map(str.rstrip, self.simulator.device_messages())): self.ui.textEditDevices.append(device_message) for log_msg in filter(None, map(str.rstrip, self.simulator.read_log_messages())): self.ui.textEditSimulation.append(log_msg) transcript = self.__get_full_transcript() for line in transcript[self.current_transcript_index:]: self.ui.textEditTranscript.append(line) self.current_transcript_index = len(transcript) current_repeat = str(self.simulator.current_repeat + 1) if self.simulator.is_simulating else "-" self.ui.lblCurrentRepeatValue.setText(current_repeat) current_item = self.simulator.current_item.index() if self.simulator.is_simulating else "-" self.ui.lblCurrentItemValue.setText(current_item) def update_rx_graphics_view(self): if self.scene_manager is None or not self.ui.graphicsViewPreview.isEnabled(): return self.scene_manager.end = self.simulator.sniffer.rcv_device.current_index self.scene_manager.init_scene() self.scene_manager.show_full_scene() self.ui.graphicsViewPreview.update() def reset(self): self.ui.textEditDevices.clear() self.ui.textEditSimulation.clear() self.ui.textEditTranscript.clear() self.current_transcript_index = 0 self.ui.lblCurrentRepeatValue.setText("-") self.ui.lblCurrentItemValue.setText("-") def emit_editing_finished_signals(self): if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_editing_finished_signals() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_editing_finished_signals() if self.sniff_settings_widget: self.sniff_settings_widget.emit_editing_finished_signals() def update_transcript_view(self): self.ui.textEditTranscript.setText("\n".join(self.__get_full_transcript())) def closeEvent(self, event: QCloseEvent): self.timer.stop() self.simulator.stop() time.sleep(0.1) self.simulator.cleanup() self.emit_editing_finished_signals() if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_device_parameters_changed() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_device_parameters_changed() if self.sniff_settings_widget: self.sniff_settings_widget.emit_sniff_parameters_changed() super().closeEvent(event) @pyqtSlot() def on_simulation_started(self): for i in range(3): self.ui.tabWidgetSimulatorSettings.setTabEnabled(i, False) self.ui.checkBoxCaptureFullRX.setDisabled(True) self.reset() self.timer.start(self.update_interval) self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-stop")) self.ui.btnStartStop.setText("Stop") if not self.rx_needed: return rx_device = self.simulator.sniffer.rcv_device for item in self.scene_manager.scene.items(): if isinstance(item, QGraphicsTextItem): self.scene_manager.scene.removeItem(item) if hasattr(rx_device.data, "real"): self.ui.graphicsViewPreview.setEnabled(True) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = rx_device.data.real else: self.scene_manager.data_array = rx_device.data.real else: self.ui.graphicsViewPreview.setEnabled(False) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = np.array([]) else: self.scene_manager.data_array = np.array([]) self.scene_manager.scene.addText("Could not generate RX preview.") @pyqtSlot() def on_simulation_stopped(self): self.ui.tabWidgetSimulatorSettings.setTabEnabled(0, True) self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, self.rx_needed) self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, self.tx_needed) self.timer.stop() self.update_view() self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStartStop.setText("Start") self.ui.checkBoxCaptureFullRX.setEnabled(True) @pyqtSlot() def on_btn_log_all_clicked(self): self.simulator_scene.log_all_items(True) @pyqtSlot() def on_btn_log_none_clicked(self): self.simulator_scene.log_all_items(False) @pyqtSlot() def on_btn_toggle_clicked(self): self.simulator_scene.log_toggle_selected_items() @pyqtSlot() def on_btn_save_log_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save log", "", "Log file (*.log)") if file_path[0] == "": return log_string = self.ui.textEditSimulation.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(log_string) except Exception as e: QMessageBox.critical(self, "Error saving log", e.args[0]) @pyqtSlot() def on_btn_save_transcript_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save transcript", "", "Text file (*.txt)") if file_path[0] == "": return transcript = self.ui.textEditTranscript.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(transcript) except Exception as e: QMessageBox.critical(self, "Error saving transcript", e.args[0]) @pyqtSlot() def on_btn_start_stop_clicked(self): if self.simulator.is_simulating: self.simulator.stop() else: if self.rx_needed: self.device_settings_rx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() self.simulator.sniffer.rcv_device.current_index = 0 self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() if self.tx_needed: self.device_settings_tx_widget.emit_editing_finished_signals() self.simulator.start() @pyqtSlot() def on_timer_timeout(self): self.update_view() self.update_rx_graphics_view() @pyqtSlot() def on_selected_rx_device_changed(self): dev_name = self.device_settings_rx_widget.ui.cbDevice.currentText() self.simulator.sniffer.device_name = dev_name self.device_settings_rx_widget.device = self.simulator.sniffer.rcv_device @pyqtSlot() def on_selected_tx_device_changed(self): old_name = self.simulator.sender.device_name try: dev_name = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator.sender.device_name = dev_name self.device_settings_tx_widget.device = self.simulator.sender.device except Exception as e: self.device_settings_tx_widget.ui.cbDevice.setCurrentText(old_name) Errors.generic_error("Error occurred", str(e)) @pyqtSlot() def on_btn_test_sniff_settings_clicked(self): def on_dialog_finished(): self.device_settings_rx_widget.bootstrap(self.project_manager.simulator_rx_conf) self.sniff_settings_widget.bootstrap(self.project_manager.device_conf) self.device_settings_rx_widget.emit_device_parameters_changed() self.sniff_settings_widget.emit_sniff_parameters_changed() psd = ProtocolSniffDialog(self.project_manager, signals=self.sniff_settings_widget.signals, parent=self) psd.device_settings_widget.bootstrap(self.project_manager.simulator_rx_conf) psd.device_settings_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) psd.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) psd.finished.connect(on_dialog_finished) psd.ui.btnAccept.hide() psd.show() @pyqtSlot() def on_radio_button_transcript_hex_clicked(self): self.update_transcript_view() @pyqtSlot() def on_radio_button_transcript_bit_clicked(self): self.update_transcript_view() @pyqtSlot() def on_checkbox_capture_full_rx_clicked(self): self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager = LiveSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) @pyqtSlot() def on_btn_save_rx_clicked(self): rx_device = self.simulator.sniffer.rcv_device if isinstance(rx_device.data, np.ndarray): filename = FileOperator.get_save_file_name("simulation_capture.complex") if filename: rx_device.data[:rx_device.current_index].tofile(filename) self.rx_file_saved.emit(filename) @pyqtSlot() def on_btn_open_in_analysis_clicked(self): text = self.ui.textEditTranscript.toPlainText() if len(text) > 0: self.open_in_analysis_requested.emit(text) self.close()
class SimulatorDialog(QDialog): rx_parameters_changed = pyqtSignal(dict) tx_parameters_changed = pyqtSignal(dict) sniff_parameters_changed = pyqtSignal(dict) def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.simulator_config = simulator_config self.simulator_scene = SimulatorScene( mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() self.device_settings_rx_widget = DeviceSettingsWidget( project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget( self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, real_time=True, network_raw_mode=True) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget( 0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget( 1, self.sniff_settings_widget) self.device_settings_tx_widget = DeviceSettingsWidget( project_manager, is_tx=True, backend_handler=self.backend_handler) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget( 0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget( 1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=self.sniff_settings_widget.sniffer, sender=EndlessSender( self.backend_handler, send_device)) self.device_settings_tx_widget.device = self.simulator.sender.device self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) self.update_buttons() self.create_connects() self.__bootstrap_device_settings(self.device_settings_rx_widget, project_manager.simulator_rx_conf) self.__bootstrap_sniff_settings(self.sniff_settings_widget, project_manager.simulator_rx_conf) self.__bootstrap_device_settings(self.device_settings_tx_widget, project_manager.simulator_tx_conf) @staticmethod def __bootstrap_device_settings(device_widget: DeviceSettingsWidget, config: dict): mapping = { "frequency": "spinBoxFreq", "sample_rate": "spinBoxSampleRate", "bandwidth": "spinBoxBandwidth", "gain": "spinBoxGain", "if_gain": "spinBoxIFGain", "baseband_gain": "spinBoxBasebandGain", "freq_correction": "spinBoxFreqCorrection" } if "name" in config: device_widget.ui.cbDevice.setCurrentText(config["name"]) for key, value in config.items(): widget = mapping.get(key, None) if widget: getattr(device_widget.ui, widget).setValue(value) device_widget.emit_editing_finished_signals() @staticmethod def __bootstrap_sniff_settings(sniff_widget: SniffSettingsWidget, config: dict): for key, value in config.items(): if key == "bit_len": sniff_widget.ui.spinbox_sniff_BitLen.setValue(value) elif key == "center": sniff_widget.ui.spinbox_sniff_Center.setValue(value) elif key == "noise": sniff_widget.ui.spinbox_sniff_Noise.setValue(value) elif key == "tolerance": sniff_widget.ui.spinbox_sniff_ErrorTolerance.setValue(value) elif key == "modulation_index": sniff_widget.ui.combox_sniff_Modulation.setCurrentIndex( int(value)) elif key == "decoding_name": sniff_widget.ui.comboBox_sniff_encoding.setCurrentText(value) sniff_widget.emit_editing_finished_signals() def create_connects(self): self.device_settings_rx_widget.selected_device_changed.connect( self.on_selected_rx_device_changed) self.device_settings_rx_widget.device_parameters_changed.connect( self.rx_parameters_changed.emit) self.device_settings_tx_widget.selected_device_changed.connect( self.on_selected_tx_device_changed) self.device_settings_tx_widget.device_parameters_changed.connect( self.tx_parameters_changed.emit) self.sniff_settings_widget.sniff_parameters_changed.connect( self.sniff_parameters_changed.emit) self.simulator_scene.selectionChanged.connect(self.update_buttons) self.simulator_config.items_updated.connect(self.update_buttons) self.ui.btnLogAll.clicked.connect(self.on_btn_log_all_clicked) self.ui.btnLogNone.clicked.connect(self.on_btn_log_none_clicked) self.ui.btnToggleLog.clicked.connect(self.on_btn_toggle_clicked) self.ui.btnStartStop.clicked.connect(self.on_start_stop_clicked) self.ui.btnSaveLog.clicked.connect(self.on_save_log_clicked) self.timer.timeout.connect(self.on_timer_timeout) self.simulator.simulation_started.connect(self.on_simulation_started) self.simulator.simulation_stopped.connect(self.on_simulation_stopped) def on_btn_log_all_clicked(self): self.simulator_scene.log_all_items(True) def on_btn_log_none_clicked(self): self.simulator_scene.log_all_items(False) def on_btn_toggle_clicked(self): self.simulator_scene.log_toggle_selected_items() def update_buttons(self): selectable_items = self.simulator_scene.selectable_items() all_items_selected = all(item.model_item.logging_active for item in selectable_items) any_item_selected = any(item.model_item.logging_active for item in selectable_items) self.ui.btnToggleLog.setEnabled( len(self.simulator_scene.selectedItems())) self.ui.btnLogAll.setEnabled(not all_items_selected) self.ui.btnLogNone.setEnabled(any_item_selected) def update_view(self): txt = self.ui.textEditDevices.toPlainText() device_messages = self.simulator.device_messages() if len(device_messages) > 1: self.ui.textEditDevices.setPlainText(txt + device_messages) txt = self.ui.textEditSimulation.toPlainText() simulator_messages = self.simulator.read_messages() if len(simulator_messages) > 1: self.ui.textEditSimulation.setPlainText(txt + simulator_messages) self.ui.textEditSimulation.verticalScrollBar().setValue( self.ui.textEditSimulation.verticalScrollBar().maximum()) current_repeat = str(self.simulator.current_repeat + 1) if self.simulator.is_simulating else "-" self.ui.lblCurrentRepeatValue.setText(current_repeat) current_item = self.simulator.current_item.index( ) if self.simulator.is_simulating else "-" self.ui.lblCurrentItemValue.setText(current_item) def update_rx_graphics_view(self): if not self.ui.graphicsViewPreview.isEnabled(): return self.scene_manager.end = self.simulator.sniffer.rcv_device.current_index self.scene_manager.init_scene() self.scene_manager.show_full_scene() self.ui.graphicsViewPreview.update() def on_save_log_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save log", "", "Log file (*.log)") if file_path[0] == "": return log_string = self.ui.textEditSimulation.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(log_string) except Exception as e: QMessageBox.critical(self, "Error saving log", e.args[0]) def on_start_stop_clicked(self): if self.simulator.is_simulating: self.simulator.stop() else: self.device_settings_rx_widget.emit_editing_finished_signals() self.device_settings_tx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() self.simulator.start() def on_simulation_started(self): self.reset() self.timer.start(self.update_interval) self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-stop")) self.ui.btnStartStop.setText("Stop") rx_device = self.simulator.sniffer.rcv_device for item in self.scene_manager.scene.items(): if isinstance(item, QGraphicsTextItem): self.scene_manager.scene.removeItem(item) if hasattr(rx_device.data, "real"): self.ui.graphicsViewPreview.setEnabled(True) self.scene_manager.data_array = rx_device.data.real else: self.ui.graphicsViewPreview.setEnabled(False) self.scene_manager.data_array = np.array([]) self.scene_manager.scene.addText("Could not generate RX preview.") def on_simulation_stopped(self): self.timer.stop() self.update_view() self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStartStop.setText("Start") def reset(self): self.ui.textEditDevices.clear() self.ui.textEditSimulation.clear() self.ui.lblCurrentRepeatValue.setText("-") self.ui.lblCurrentItemValue.setText("-") def emit_editing_finished_signals(self): self.device_settings_rx_widget.emit_editing_finished_signals() self.device_settings_tx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() def closeEvent(self, event: QCloseEvent): self.emit_editing_finished_signals() self.device_settings_rx_widget.emit_device_parameters_changed() self.device_settings_tx_widget.emit_device_parameters_changed() self.sniff_settings_widget.emit_sniff_parameters_changed() self.timer.stop() self.simulator.stop() time.sleep(0.1) self.simulator.cleanup() super().closeEvent(event) @pyqtSlot() def on_timer_timeout(self): self.update_view() self.update_rx_graphics_view() @pyqtSlot() def on_selected_rx_device_changed(self): dev_name = self.device_settings_rx_widget.ui.cbDevice.currentText() self.simulator.sniffer.device_name = dev_name self.device_settings_rx_widget.device = self.simulator.sniffer.rcv_device @pyqtSlot() def on_selected_tx_device_changed(self): old_name = self.simulator.sender.device_name try: dev_name = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator.sender.device_name = dev_name self.device_settings_tx_widget.device = self.simulator.sender.device except Exception as e: self.device_settings_tx_widget.ui.cbDevice.setCurrentText(old_name) Errors.generic_error("Error occurred", str(e))
def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, signals: list = None, signal_tree_model=None, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.Window) self.simulator_config = simulator_config # type: SimulatorConfiguration self.rx_needed = self.simulator_config.rx_needed self.tx_needed = self.simulator_config.tx_needed self.current_transcript_index = 0 self.simulator_scene = SimulatorScene(mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() if self.rx_needed: self.device_settings_rx_widget = DeviceSettingsWidget(project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget(self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, network_raw_mode=True, signals=signals) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(1, self.sniff_settings_widget) sniffer = self.sniff_settings_widget.sniffer self.scene_manager = SniffSceneManager(np.array([], dtype=sniffer.rcv_device.data_type), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.device_settings_rx_widget = self.sniff_settings_widget = self.scene_manager = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, False) self.ui.graphicsViewPreview.hide() self.ui.btnSaveRX.hide() self.ui.checkBoxCaptureFullRX.hide() sniffer = None if self.tx_needed: self.device_settings_tx_widget = DeviceSettingsWidget(project_manager, is_tx=True, backend_handler=self.backend_handler, continuous_send_mode=True) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, signal_tree_model=signal_tree_model, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() sender = EndlessSender(self.backend_handler, send_device) else: self.device_settings_tx_widget = self.modulation_settings_widget = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, False) sender = None self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=sniffer, sender=sender) if self.device_settings_tx_widget: self.device_settings_tx_widget.device = self.simulator.sender.device self.update_buttons() self.create_connects() if self.device_settings_rx_widget: self.device_settings_rx_widget.bootstrap(project_manager.simulator_rx_conf) if self.device_settings_tx_widget: self.device_settings_tx_widget.bootstrap(project_manager.simulator_tx_conf) self.ui.textEditTranscript.setFont(util.get_monospace_font()) if settings.read('default_view', 0, int) == 1: self.ui.radioButtonTranscriptHex.setChecked(True)
class SimulatorDialog(QDialog): rx_parameters_changed = pyqtSignal(dict) tx_parameters_changed = pyqtSignal(dict) sniff_parameters_changed = pyqtSignal(dict) open_in_analysis_requested = pyqtSignal(str) rx_file_saved = pyqtSignal(str) def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, signals: list = None, signal_tree_model=None, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.Window) self.simulator_config = simulator_config # type: SimulatorConfiguration self.rx_needed = self.simulator_config.rx_needed self.tx_needed = self.simulator_config.tx_needed self.current_transcript_index = 0 self.simulator_scene = SimulatorScene(mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() if self.rx_needed: self.device_settings_rx_widget = DeviceSettingsWidget(project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget(self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, network_raw_mode=True, signals=signals) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(1, self.sniff_settings_widget) sniffer = self.sniff_settings_widget.sniffer self.scene_manager = SniffSceneManager(np.array([], dtype=sniffer.rcv_device.data_type), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.device_settings_rx_widget = self.sniff_settings_widget = self.scene_manager = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, False) self.ui.graphicsViewPreview.hide() self.ui.btnSaveRX.hide() self.ui.checkBoxCaptureFullRX.hide() sniffer = None if self.tx_needed: self.device_settings_tx_widget = DeviceSettingsWidget(project_manager, is_tx=True, backend_handler=self.backend_handler, continuous_send_mode=True) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, signal_tree_model=signal_tree_model, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() sender = EndlessSender(self.backend_handler, send_device) else: self.device_settings_tx_widget = self.modulation_settings_widget = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, False) sender = None self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=sniffer, sender=sender) if self.device_settings_tx_widget: self.device_settings_tx_widget.device = self.simulator.sender.device self.update_buttons() self.create_connects() if self.device_settings_rx_widget: self.device_settings_rx_widget.bootstrap(project_manager.simulator_rx_conf) if self.device_settings_tx_widget: self.device_settings_tx_widget.bootstrap(project_manager.simulator_tx_conf) self.ui.textEditTranscript.setFont(util.get_monospace_font()) if settings.read('default_view', 0, int) == 1: self.ui.radioButtonTranscriptHex.setChecked(True) def create_connects(self): if self.rx_needed: self.device_settings_rx_widget.selected_device_changed.connect(self.on_selected_rx_device_changed) self.device_settings_rx_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) self.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) self.ui.btnSaveRX.clicked.connect(self.on_btn_save_rx_clicked) self.ui.checkBoxCaptureFullRX.clicked.connect(self.on_checkbox_capture_full_rx_clicked) self.ui.btnTestSniffSettings.clicked.connect(self.on_btn_test_sniff_settings_clicked) self.ui.btnOpenInAnalysis.clicked.connect(self.on_btn_open_in_analysis_clicked) if self.tx_needed: self.device_settings_tx_widget.selected_device_changed.connect(self.on_selected_tx_device_changed) self.device_settings_tx_widget.device_parameters_changed.connect(self.tx_parameters_changed.emit) self.ui.radioButtonTranscriptBit.clicked.connect(self.on_radio_button_transcript_bit_clicked) self.ui.radioButtonTranscriptHex.clicked.connect(self.on_radio_button_transcript_hex_clicked) self.simulator_scene.selectionChanged.connect(self.update_buttons) self.simulator_config.items_updated.connect(self.update_buttons) self.ui.btnLogAll.clicked.connect(self.on_btn_log_all_clicked) self.ui.btnLogNone.clicked.connect(self.on_btn_log_none_clicked) self.ui.btnToggleLog.clicked.connect(self.on_btn_toggle_clicked) self.ui.btnStartStop.clicked.connect(self.on_btn_start_stop_clicked) self.ui.btnSaveLog.clicked.connect(self.on_btn_save_log_clicked) self.ui.btnSaveTranscript.clicked.connect(self.on_btn_save_transcript_clicked) self.timer.timeout.connect(self.on_timer_timeout) self.simulator.simulation_started.connect(self.on_simulation_started) self.simulator.simulation_stopped.connect(self.on_simulation_stopped) def update_buttons(self): selectable_items = self.simulator_scene.selectable_items() all_items_selected = all(item.model_item.logging_active for item in selectable_items) any_item_selected = any(item.model_item.logging_active for item in selectable_items) self.ui.btnToggleLog.setEnabled(len(self.simulator_scene.selectedItems())) self.ui.btnLogAll.setEnabled(not all_items_selected) self.ui.btnLogNone.setEnabled(any_item_selected) def __get_full_transcript(self) -> list: return self.simulator.transcript.get_for_all_participants(all_rounds=True, use_bit=self.ui.radioButtonTranscriptBit.isChecked()) def update_view(self): for device_message in filter(None, map(str.rstrip, self.simulator.device_messages())): self.ui.textEditDevices.append(device_message) for log_msg in filter(None, map(str.rstrip, self.simulator.read_log_messages())): self.ui.textEditSimulation.append(log_msg) transcript = self.__get_full_transcript() for line in transcript[self.current_transcript_index:]: self.ui.textEditTranscript.append(line) self.current_transcript_index = len(transcript) current_repeat = str(self.simulator.current_repeat + 1) if self.simulator.is_simulating else "-" self.ui.lblCurrentRepeatValue.setText(current_repeat) current_item = self.simulator.current_item.index() if self.simulator.is_simulating else "-" self.ui.lblCurrentItemValue.setText(current_item) def update_rx_graphics_view(self): if self.scene_manager is None or not self.ui.graphicsViewPreview.isEnabled(): return self.scene_manager.end = self.simulator.sniffer.rcv_device.current_index self.scene_manager.init_scene() self.scene_manager.show_full_scene() self.ui.graphicsViewPreview.update() def reset(self): self.ui.textEditDevices.clear() self.ui.textEditSimulation.clear() self.ui.textEditTranscript.clear() self.current_transcript_index = 0 self.ui.lblCurrentRepeatValue.setText("-") self.ui.lblCurrentItemValue.setText("-") def emit_editing_finished_signals(self): if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_editing_finished_signals() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_editing_finished_signals() if self.sniff_settings_widget: self.sniff_settings_widget.emit_editing_finished_signals() def update_transcript_view(self): self.ui.textEditTranscript.setText("\n".join(self.__get_full_transcript())) def closeEvent(self, event: QCloseEvent): self.timer.stop() self.simulator.stop() self.simulator.cleanup() self.emit_editing_finished_signals() if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_device_parameters_changed() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_device_parameters_changed() if self.sniff_settings_widget: self.sniff_settings_widget.emit_sniff_parameters_changed() super().closeEvent(event) @pyqtSlot() def on_simulation_started(self): for i in range(3): self.ui.tabWidgetSimulatorSettings.setTabEnabled(i, False) self.ui.checkBoxCaptureFullRX.setDisabled(True) self.reset() self.timer.start(self.update_interval) self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-stop")) self.ui.btnStartStop.setText("Stop") if not self.rx_needed: return rx_device = self.simulator.sniffer.rcv_device for item in self.scene_manager.scene.items(): if isinstance(item, QGraphicsTextItem): self.scene_manager.scene.removeItem(item) if hasattr(rx_device.data, "real"): self.ui.graphicsViewPreview.setEnabled(True) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = rx_device.data.real else: self.scene_manager.data_array = rx_device.data.real else: self.ui.graphicsViewPreview.setEnabled(False) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = np.array([], dtype=rx_device.data_type) else: self.scene_manager.data_array = np.array([], dtype=rx_device.data_type) self.scene_manager.scene.addText("Could not generate RX preview.") @pyqtSlot() def on_simulation_stopped(self): self.ui.tabWidgetSimulatorSettings.setTabEnabled(0, True) self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, self.rx_needed) self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, self.tx_needed) self.timer.stop() self.update_view() self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStartStop.setText("Start") self.ui.checkBoxCaptureFullRX.setEnabled(True) @pyqtSlot() def on_btn_log_all_clicked(self): self.simulator_scene.log_all_items(True) @pyqtSlot() def on_btn_log_none_clicked(self): self.simulator_scene.log_all_items(False) @pyqtSlot() def on_btn_toggle_clicked(self): self.simulator_scene.log_toggle_selected_items() @pyqtSlot() def on_btn_save_log_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save log", "", "Log file (*.log)") if file_path[0] == "": return log_string = self.ui.textEditSimulation.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(log_string) except Exception as e: QMessageBox.critical(self, "Error saving log", e.args[0]) @pyqtSlot() def on_btn_save_transcript_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save transcript", "", "Text file (*.txt)") if file_path[0] == "": return transcript = self.ui.textEditTranscript.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(transcript) except Exception as e: QMessageBox.critical(self, "Error saving transcript", e.args[0]) @pyqtSlot() def on_btn_start_stop_clicked(self): if self.simulator.is_simulating: self.simulator.stop() else: if self.rx_needed: self.device_settings_rx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() self.simulator.sniffer.rcv_device.current_index = 0 self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() if self.tx_needed: self.device_settings_tx_widget.emit_editing_finished_signals() self.simulator.start() @pyqtSlot() def on_timer_timeout(self): self.update_view() self.update_rx_graphics_view() @pyqtSlot() def on_selected_rx_device_changed(self): dev_name = self.device_settings_rx_widget.ui.cbDevice.currentText() self.simulator.sniffer.device_name = dev_name self.device_settings_rx_widget.device = self.simulator.sniffer.rcv_device self.__set_rx_scene() @pyqtSlot() def on_selected_tx_device_changed(self): old_name = self.simulator.sender.device_name try: dev_name = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator.sender.device_name = dev_name self.device_settings_tx_widget.device = self.simulator.sender.device except Exception as e: self.device_settings_tx_widget.ui.cbDevice.setCurrentText(old_name) Errors.exception(e) @pyqtSlot() def on_btn_test_sniff_settings_clicked(self): def on_dialog_finished(): self.device_settings_rx_widget.bootstrap(self.project_manager.simulator_rx_conf) self.sniff_settings_widget.bootstrap(self.project_manager.device_conf) self.device_settings_rx_widget.emit_device_parameters_changed() self.sniff_settings_widget.emit_sniff_parameters_changed() psd = ProtocolSniffDialog(self.project_manager, signals=self.sniff_settings_widget.signals, parent=self) psd.device_settings_widget.bootstrap(self.project_manager.simulator_rx_conf) psd.device_settings_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) psd.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) psd.finished.connect(on_dialog_finished) psd.ui.btnAccept.hide() psd.show() @pyqtSlot() def on_radio_button_transcript_hex_clicked(self): self.update_transcript_view() @pyqtSlot() def on_radio_button_transcript_bit_clicked(self): self.update_transcript_view() def __set_rx_scene(self): if not self.rx_needed: return if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager = LiveSceneManager(np.array([], dtype=self.simulator.sniffer.rcv_device.data_type), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.scene_manager = SniffSceneManager(np.array([], dtype=self.simulator.sniffer.rcv_device.data_type), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) @pyqtSlot() def on_checkbox_capture_full_rx_clicked(self): self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() self.__set_rx_scene() @pyqtSlot() def on_btn_save_rx_clicked(self): rx_device = self.simulator.sniffer.rcv_device if isinstance(rx_device.data, np.ndarray) or isinstance(rx_device.data, IQArray): data = IQArray(rx_device.data[:rx_device.current_index]) filename = FileOperator.ask_signal_file_name_and_save("simulation_capture", data, sample_rate=rx_device.sample_rate, parent=self) if filename: data.tofile(filename) self.rx_file_saved.emit(filename) @pyqtSlot() def on_btn_open_in_analysis_clicked(self): text = self.ui.textEditTranscript.toPlainText() if len(text) > 0: self.open_in_analysis_requested.emit(text) self.close()
def __init__(self, compare_frame_controller: CompareFrameController, generator_tab_controller: GeneratorTabController, project_manager: ProjectManager, parent): super().__init__(parent) self.project_manager = project_manager self.compare_frame_controller = compare_frame_controller self.generator_tab_controller = generator_tab_controller self.proto_analyzer = compare_frame_controller.proto_analyzer self.simulator_config = SimulatorConfiguration(self.project_manager) self.sim_expression_parser = SimulatorExpressionParser(self.simulator_config) SimulatorItem.simulator_config = self.simulator_config SimulatorItem.expression_parser = self.sim_expression_parser self.ui = Ui_SimulatorTab() self.ui.setupUi(self) util.set_splitter_stylesheet(self.ui.splitter) util.set_splitter_stylesheet(self.ui.splitterLeftRight) self.ui.splitter.setSizes([self.width() / 0.7, self.width() / 0.3]) self.ui.treeProtocols.setHeaderHidden(True) self.tree_model = self.generator_tab_controller.tree_model self.ui.treeProtocols.setModel(self.tree_model) self.participant_table_model = ParticipantTableModel(project_manager.participants) self.ui.tableViewParticipants.setModel(self.participant_table_model) self.participant_table_model.update() self.simulator_message_field_model = SimulatorMessageFieldModel(self) self.ui.tblViewFieldValues.setModel(self.simulator_message_field_model) self.ui.tblViewFieldValues.setItemDelegateForColumn(1, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn(2, ComboBoxDelegate(SimulatorProtocolLabel.VALUE_TYPES, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn(3, ProtocolValueDelegate(controller=self, parent=self.ui.tblViewFieldValues)) self.project_manager.reload_field_types() self.update_field_name_column() self.simulator_message_table_model = SimulatorMessageTableModel(self.project_manager, self) self.ui.tblViewMessage.setModel(self.simulator_message_table_model) self.ui.ruleCondLineEdit.setValidator(RuleExpressionValidator(self.sim_expression_parser, is_formula=False)) self.completer_model = QStringListModel([]) self.ui.ruleCondLineEdit.setCompleter(QCompleter(self.completer_model, self.ui.ruleCondLineEdit)) self.ui.ruleCondLineEdit.setToolTip(self.sim_expression_parser.rule_condition_help) self.simulator_scene = SimulatorScene(mode=0, simulator_config=self.simulator_config) self.simulator_scene.tree_root_item = compare_frame_controller.proto_tree_model.rootItem self.ui.gvSimulator.setScene(self.simulator_scene) self.ui.gvSimulator.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.ui.gvSimulator.proto_analyzer = compare_frame_controller.proto_analyzer self.__active_item = None self.ui.listViewSimulate.setModel(SimulatorParticipantListModel(self.simulator_config)) self.ui.spinBoxNRepeat.setValue(self.project_manager.simulator_num_repeat) self.ui.spinBoxTimeout.setValue(self.project_manager.simulator_timeout_ms) self.ui.spinBoxRetries.setValue(self.project_manager.simulator_retries) self.ui.comboBoxError.setCurrentIndex(self.project_manager.simulator_error_handling_index) # place save/load button at corner of tab widget frame = QFrame(parent=self) frame.setLayout(QHBoxLayout()) frame.setFrameStyle(frame.NoFrame) self.ui.btnSave = QToolButton(self.ui.tab) self.ui.btnSave.setIcon(QIcon.fromTheme("document-save")) frame.layout().addWidget(self.ui.btnSave) self.ui.btnLoad = QToolButton(self.ui.tab) self.ui.btnLoad.setIcon(QIcon.fromTheme("document-open")) frame.layout().addWidget(self.ui.btnLoad) frame.layout().setContentsMargins(0, 0, 0, 0) self.ui.tabWidget.setCornerWidget(frame) self.ui.splitterLeftRight.setSizes([0.2 * self.width(), 0.8 * self.width()]) self.create_connects()
class SimulatorTabController(QWidget): open_in_analysis_requested = pyqtSignal(str) rx_file_saved = pyqtSignal(str) def __init__(self, compare_frame_controller: CompareFrameController, generator_tab_controller: GeneratorTabController, project_manager: ProjectManager, parent): super().__init__(parent) self.project_manager = project_manager self.compare_frame_controller = compare_frame_controller self.generator_tab_controller = generator_tab_controller self.proto_analyzer = compare_frame_controller.proto_analyzer self.simulator_config = SimulatorConfiguration(self.project_manager) self.sim_expression_parser = SimulatorExpressionParser(self.simulator_config) SimulatorItem.simulator_config = self.simulator_config SimulatorItem.expression_parser = self.sim_expression_parser self.ui = Ui_SimulatorTab() self.ui.setupUi(self) util.set_splitter_stylesheet(self.ui.splitter) util.set_splitter_stylesheet(self.ui.splitterLeftRight) self.ui.splitter.setSizes([self.width() / 0.7, self.width() / 0.3]) self.ui.treeProtocols.setHeaderHidden(True) self.tree_model = self.generator_tab_controller.tree_model self.ui.treeProtocols.setModel(self.tree_model) self.participant_table_model = ParticipantTableModel(project_manager.participants) self.ui.tableViewParticipants.setModel(self.participant_table_model) self.participant_table_model.update() self.simulator_message_field_model = SimulatorMessageFieldModel(self) self.ui.tblViewFieldValues.setModel(self.simulator_message_field_model) self.ui.tblViewFieldValues.setItemDelegateForColumn(1, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn(2, ComboBoxDelegate(SimulatorProtocolLabel.VALUE_TYPES, parent=self.ui.tblViewFieldValues)) self.ui.tblViewFieldValues.setItemDelegateForColumn(3, ProtocolValueDelegate(controller=self, parent=self.ui.tblViewFieldValues)) self.project_manager.reload_field_types() self.update_field_name_column() self.simulator_message_table_model = SimulatorMessageTableModel(self.project_manager, self) self.ui.tblViewMessage.setModel(self.simulator_message_table_model) self.ui.ruleCondLineEdit.setValidator(RuleExpressionValidator(self.sim_expression_parser, is_formula=False)) self.completer_model = QStringListModel([]) self.ui.ruleCondLineEdit.setCompleter(QCompleter(self.completer_model, self.ui.ruleCondLineEdit)) self.ui.ruleCondLineEdit.setToolTip(self.sim_expression_parser.rule_condition_help) self.simulator_scene = SimulatorScene(mode=0, simulator_config=self.simulator_config) self.simulator_scene.tree_root_item = compare_frame_controller.proto_tree_model.rootItem self.ui.gvSimulator.setScene(self.simulator_scene) self.ui.gvSimulator.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.ui.gvSimulator.proto_analyzer = compare_frame_controller.proto_analyzer self.__active_item = None self.ui.listViewSimulate.setModel(SimulatorParticipantListModel(self.simulator_config)) self.ui.spinBoxNRepeat.setValue(self.project_manager.simulator_num_repeat) self.ui.spinBoxTimeout.setValue(self.project_manager.simulator_timeout_ms) self.ui.spinBoxRetries.setValue(self.project_manager.simulator_retries) self.ui.comboBoxError.setCurrentIndex(self.project_manager.simulator_error_handling_index) # place save/load button at corner of tab widget frame = QFrame(parent=self) frame.setLayout(QHBoxLayout()) frame.setFrameStyle(frame.NoFrame) self.ui.btnSave = QToolButton(self.ui.tab) self.ui.btnSave.setIcon(QIcon.fromTheme("document-save")) frame.layout().addWidget(self.ui.btnSave) self.ui.btnLoad = QToolButton(self.ui.tab) self.ui.btnLoad.setIcon(QIcon.fromTheme("document-open")) frame.layout().addWidget(self.ui.btnLoad) frame.layout().setContentsMargins(0, 0, 0, 0) self.ui.tabWidget.setCornerWidget(frame) self.ui.splitterLeftRight.setSizes([0.2 * self.width(), 0.8 * self.width()]) self.create_connects() def refresh_field_types_for_labels(self): for msg in self.simulator_config.get_all_messages(): for lbl in (lbl for lbl in msg.message_type if lbl.field_type is not None): msg.message_type.change_field_type_of_label(lbl, self.field_types_by_caption.get(lbl.field_type.caption, None)) self.update_field_name_column() self.update_ui() @property def field_types(self): return self.project_manager.field_types @property def field_types_by_caption(self): return self.project_manager.field_types_by_caption def update_field_name_column(self): field_types = [ft.caption for ft in self.field_types] self.ui.tblViewFieldValues.setItemDelegateForColumn(0, ComboBoxDelegate(field_types, is_editable=True, return_index=False, parent=self.ui.tblViewFieldValues)) def create_connects(self): self.ui.btnChooseCommand.clicked.connect(self.on_btn_choose_command_clicked) self.ui.lineEditTriggerCommand.textChanged.connect(self.on_line_edit_trigger_command_text_changed) self.ui.checkBoxPassTranscriptSTDIN.clicked.connect(self.on_check_box_pass_transcript_STDIN_clicked) self.ui.doubleSpinBoxSleep.editingFinished.connect(self.on_spinbox_sleep_editing_finished) self.ui.ruleCondLineEdit.textChanged.connect(self.on_rule_cond_line_edit_text_changed) self.ui.btnStartSim.clicked.connect(self.on_btn_simulate_clicked) self.ui.goto_combobox.currentIndexChanged.connect(self.on_goto_combobox_index_changed) self.ui.spinBoxRepeat.valueChanged.connect(self.on_repeat_value_changed) self.ui.cbViewType.currentIndexChanged.connect(self.on_view_type_changed) self.ui.tblViewMessage.create_label_triggered.connect(self.create_simulator_label) self.ui.tblViewMessage.open_modulator_dialog_clicked.connect(self.open_modulator_dialog) self.ui.tblViewMessage.selectionModel().selectionChanged.connect(self.on_table_selection_changed) self.ui.tabWidget.currentChanged.connect(self.on_selected_tab_changed) self.ui.btnSave.clicked.connect(self.on_btn_save_clicked) self.ui.btnLoad.clicked.connect(self.on_btn_load_clicked) self.ui.listViewSimulate.model().participant_simulate_changed.connect(self.on_participant_simulate_changed) self.ui.btnAddParticipant.clicked.connect(self.ui.tableViewParticipants.on_add_action_triggered) self.ui.btnRemoveParticipant.clicked.connect(self.ui.tableViewParticipants.on_remove_action_triggered) self.ui.btnUp.clicked.connect(self.ui.tableViewParticipants.on_move_up_action_triggered) self.ui.btnDown.clicked.connect(self.ui.tableViewParticipants.on_move_down_action_triggered) self.participant_table_model.participant_edited.connect(self.on_participant_edited) self.tree_model.modelReset.connect(self.refresh_tree) self.simulator_scene.selectionChanged.connect(self.on_simulator_scene_selection_changed) self.simulator_scene.files_dropped.connect(self.on_files_dropped) self.simulator_message_field_model.protocol_label_updated.connect(self.item_updated) self.ui.gvSimulator.message_updated.connect(self.item_updated) self.ui.gvSimulator.consolidate_messages_clicked.connect(self.consolidate_messages) self.simulator_config.items_added.connect(self.refresh_message_table) self.simulator_config.items_updated.connect(self.refresh_message_table) self.simulator_config.items_moved.connect(self.refresh_message_table) self.simulator_config.items_deleted.connect(self.refresh_message_table) self.simulator_config.participants_changed.connect(self.on_participants_changed) self.simulator_config.item_dict_updated.connect(self.on_item_dict_updated) self.simulator_config.active_participants_updated.connect(self.on_active_participants_updated) self.ui.gvSimulator.message_updated.connect(self.on_message_source_or_destination_updated) self.ui.spinBoxNRepeat.valueChanged.connect(self.on_spinbox_num_repeat_value_changed) self.ui.spinBoxTimeout.valueChanged.connect(self.on_spinbox_timeout_value_changed) self.ui.comboBoxError.currentIndexChanged.connect(self.on_combobox_error_handling_index_changed) self.ui.spinBoxRetries.valueChanged.connect(self.on_spinbox_retries_value_changed) self.ui.tblViewFieldValues.item_link_clicked.connect(self.on_table_item_link_clicked) self.ui.tblViewMessage.edit_label_triggered.connect(self.on_edit_label_triggered) self.ui.spinBoxCounterStart.editingFinished.connect(self.on_spinbox_counter_start_editing_finished) self.ui.spinBoxCounterStep.editingFinished.connect(self.on_spinbox_counter_step_editing_finished) def consolidate_messages(self): self.simulator_config.consolidate_messages() def on_repeat_value_changed(self, value): self.active_item.repeat = value self.simulator_config.items_updated.emit([self.active_item]) def on_item_dict_updated(self): self.completer_model.setStringList(self.sim_expression_parser.get_identifiers()) def on_selected_tab_changed(self, index: int): if index == 0: if self.active_item is not None: self.ui.gvSimulator.jump_to_item(self.active_item) else: self.update_ui() else: self.ui.tblViewMessage.resize_columns() self.update_vertical_table_header() def refresh_message_table(self): self.simulator_message_table_model.protocol.messages[:] = self.simulator_config.get_all_messages() self.simulator_message_table_model.update() if isinstance(self.active_item, SimulatorMessage): self.simulator_message_field_model.update() self.ui.tblViewMessage.resize_columns() self.update_ui() def load_config_from_xml_tag(self, xml_tag, update_before=True): if xml_tag is None: return if update_before: self.simulator_config.on_project_updated() self.simulator_config.load_from_xml(xml_tag, self.proto_analyzer.message_types) self.project_manager.project_updated.emit() def load_simulator_file(self, filename: str): try: tree = ET.parse(filename) self.load_config_from_xml_tag(tree.getroot(), update_before=False) except Exception as e: logger.exception(e) def save_simulator_file(self, filename: str): tag = self.simulator_config.save_to_xml(standalone=True) util.write_xml_to_file(tag, filename) def close_all(self): self.simulator_scene.clear_all() @pyqtSlot(int, int, int) def create_simulator_label(self, msg_index: int, start: int, end: int): con = self.simulator_message_table_model.protocol start, end = con.convert_range(start, end - 1, self.ui.cbViewType.currentIndex(), 0, False, msg_index) lbl = self.simulator_config.add_label(start=start, end=end, parent_item=con.messages[msg_index]) try: index = self.simulator_message_field_model.message_type.index(lbl) self.ui.tblViewFieldValues.edit(self.simulator_message_field_model.createIndex(index, 0)) except ValueError: pass @pyqtSlot() def open_modulator_dialog(self): selected_message = self.simulator_message_table_model.protocol.messages[self.ui.tblViewMessage.selected_rows[0]] preselected_index = selected_message.modulator_index modulator_dialog = ModulatorDialog(self.project_manager.modulators, tree_model=self.tree_model, parent=self) modulator_dialog.ui.comboBoxCustomModulations.setCurrentIndex(preselected_index) modulator_dialog.showMaximized() modulator_dialog.initialize(selected_message.encoded_bits_str[0:10]) modulator_dialog.finished.connect(self.refresh_modulators) modulator_dialog.finished.connect(self.generator_tab_controller.refresh_pause_list) @pyqtSlot() def refresh_modulators(self): # update Generator tab ... cBoxModulations = self.generator_tab_controller.ui.cBoxModulations current_index = cBoxModulations.currentIndex() cBoxModulations.clear() for modulator in self.project_manager.modulators: cBoxModulations.addItem(modulator.name) cBoxModulations.setCurrentIndex(current_index) # update Simulator tab ... index = self.sender().ui.comboBoxCustomModulations.currentIndex() for row in self.ui.tblViewMessage.selected_rows: self.simulator_message_table_model.protocol.messages[row].modulator_index = index def update_goto_combobox(self, active_item: SimulatorGotoAction): assert isinstance(active_item, SimulatorGotoAction) goto_combobox = self.ui.goto_combobox goto_combobox.blockSignals(True) goto_combobox.clear() goto_combobox.addItem("Select item ...") goto_combobox.addItems(active_item.get_valid_goto_targets()) goto_combobox.setCurrentIndex(-1) goto_combobox.blockSignals(False) index = goto_combobox.findText(self.active_item.goto_target) if index == -1: index = 0 goto_combobox.setCurrentIndex(index) def update_ui(self): if self.active_item is not None: text = self.tr("Detail view for item #") + self.active_item.index() if isinstance(self.active_item, SimulatorMessage): text += " (" + self.active_item.message_type.name + ")" self.ui.spinBoxRepeat.setValue(self.active_item.repeat) self.ui.lblEncodingDecoding.setText(self.active_item.decoder.name) self.ui.lblMsgFieldsValues.setText(text) else: self.ui.lblMsgFieldsValues.setText(self.tr("Detail view for item")) def update_vertical_table_header(self): self.simulator_message_table_model.refresh_vertical_header() self.ui.tblViewMessage.resize_vertical_header() @pyqtSlot() def on_rule_cond_line_edit_text_changed(self): self.active_item.condition = self.ui.ruleCondLineEdit.text() self.item_updated(self.active_item) @pyqtSlot() def on_view_type_changed(self): self.simulator_message_table_model.proto_view = self.ui.cbViewType.currentIndex() self.simulator_message_table_model.update() self.ui.tblViewMessage.resize_columns() @pyqtSlot() def on_goto_combobox_index_changed(self): if not isinstance(self.active_item, SimulatorGotoAction): return self.active_item.goto_target = None if self.ui.goto_combobox.currentIndex() == 0 else self.ui.goto_combobox.currentText() self.item_updated(self.active_item) @pyqtSlot() def on_simulator_scene_selection_changed(self): selected_items = self.simulator_scene.selectedItems() self.active_item = selected_items[0].model_item if selected_items else None self.update_ui() @pyqtSlot() def on_table_selection_changed(self): selection = self.ui.tblViewMessage.selectionModel().selection() if selection.isEmpty(): self.active_item = None self.ui.lNumSelectedColumns.setText("0") else: max_row = numpy.max([rng.bottom() for rng in selection]) self.active_item = self.simulator_message_table_model.protocol.messages[max_row] _, _, start, end = self.ui.tblViewMessage.selection_range() self.ui.lNumSelectedColumns.setText(str(end - start)) self.update_ui() @property def active_item(self): return self.__active_item @active_item.setter def active_item(self, value): self.__active_item = value if isinstance(self.active_item, SimulatorGotoAction): self.update_goto_combobox(self.active_item) self.ui.detail_view_widget.setCurrentIndex(1) elif isinstance(self.active_item, SimulatorMessage): self.simulator_message_field_model.update() self.ui.spinBoxRepeat.setValue(self.active_item.repeat) self.ui.lblEncodingDecoding.setText(self.active_item.decoder.name) self.ui.detail_view_widget.setCurrentIndex(2) elif (isinstance(self.active_item, SimulatorRuleCondition) and self.active_item.type != ConditionType.ELSE): self.ui.ruleCondLineEdit.setText(self.active_item.condition) self.ui.detail_view_widget.setCurrentIndex(3) elif isinstance(self.active_item, SimulatorTriggerCommandAction): self.ui.lineEditTriggerCommand.setText(self.active_item.command) self.ui.checkBoxPassTranscriptSTDIN.setChecked(self.active_item.pass_transcript) self.ui.detail_view_widget.setCurrentIndex(4) elif isinstance(self.active_item, SimulatorSleepAction): self.ui.doubleSpinBoxSleep.setValue(self.active_item.sleep_time) self.ui.detail_view_widget.setCurrentIndex(5) elif isinstance(self.active_item, SimulatorCounterAction): self.ui.spinBoxCounterStart.setValue(self.active_item.start) self.ui.spinBoxCounterStep.setValue(self.active_item.step) self.ui.detail_view_widget.setCurrentIndex(6) else: self.ui.detail_view_widget.setCurrentIndex(0) self.update_ui() @pyqtSlot() def on_btn_simulate_clicked(self): if not self.simulator_config.protocol_valid(): QMessageBox.critical(self, self.tr("Invalid protocol configuration"), self.tr( "There are some problems with your protocol configuration. Please fix them first.")) return if not len(self.simulator_config.get_all_messages()): QMessageBox.critical(self, self.tr("No messages found"), self.tr("Please add at least one message.")) return num_simulated = len([p for p in self.project_manager.participants if p.simulate]) if num_simulated == 0: if self.ui.listViewSimulate.model().rowCount() == 0: QMessageBox.critical(self, self.tr("No active participants"), self.tr("You have no active participants.<br>" "Please add a participant in the <i>Participants tab</i> and " "assign it to at least one message as <i>source</i> or <i>destination.</i>")) return else: QMessageBox.critical(self, self.tr("No participant for simulation selected"), self.tr("Please check at least one participant from the " "<i>Simulate these participants</i> list.")) return try: self.get_simulator_dialog().exec_() except Exception as e: Errors.generic_error("An error occurred", str(e)) def get_simulator_dialog(self) -> SimulatorDialog: protos = [p for proto_list in self.tree_model.protocols.values() for p in proto_list] signals = [p.signal for p in protos if p.signal is not None] s = SimulatorDialog(self.simulator_config, self.project_manager.modulators, self.sim_expression_parser, self.project_manager, signals=signals, signal_tree_model=self.tree_model, parent=self) s.rx_parameters_changed.connect(self.project_manager.on_simulator_rx_parameters_changed) s.sniff_parameters_changed.connect(self.project_manager.on_simulator_sniff_parameters_changed) s.tx_parameters_changed.connect(self.project_manager.on_simulator_tx_parameters_changed) s.open_in_analysis_requested.connect(self.open_in_analysis_requested.emit) s.rx_file_saved.connect(self.rx_file_saved.emit) return s @pyqtSlot() def on_btn_choose_command_clicked(self): file_name, ok = QFileDialog.getOpenFileName(self, self.tr("Choose program"), QDir.homePath()) if file_name is not None and ok: self.ui.lineEditTriggerCommand.setText(file_name) @pyqtSlot() def on_line_edit_trigger_command_text_changed(self): self.active_item.command = self.ui.lineEditTriggerCommand.text() self.item_updated(self.active_item) @pyqtSlot() def on_check_box_pass_transcript_STDIN_clicked(self): self.active_item.pass_transcript = self.ui.checkBoxPassTranscriptSTDIN.isChecked() self.item_updated(self.active_item) @pyqtSlot() def on_spinbox_counter_start_editing_finished(self): self.active_item.start = self.ui.spinBoxCounterStart.value() self.item_updated(self.active_item) @pyqtSlot() def on_spinbox_counter_step_editing_finished(self): self.active_item.step = self.ui.spinBoxCounterStep.value() self.item_updated(self.active_item) @pyqtSlot() def on_spinbox_sleep_editing_finished(self): self.active_item.sleep_time = self.ui.doubleSpinBoxSleep.value() self.item_updated(self.active_item) @pyqtSlot() def on_participants_changed(self): self.update_vertical_table_header() self.participant_table_model.update() self.ui.listViewSimulate.model().update() def item_updated(self, item: SimulatorItem): self.simulator_config.items_updated.emit([item]) @pyqtSlot() def refresh_tree(self): self.ui.treeProtocols.expandAll() @pyqtSlot() def on_btn_save_clicked(self): filename = FileOperator.get_save_file_name(initial_name="myprofile.sim.xml", caption="Save simulator profile") if filename: self.save_simulator_file(filename) @pyqtSlot() def on_btn_load_clicked(self): dialog = FileOperator.get_open_dialog(False, parent=self, name_filter="simulator") if dialog.exec_(): self.load_simulator_file(dialog.selectedFiles()[0]) @pyqtSlot() def on_participant_edited(self): self.project_manager.project_updated.emit() @pyqtSlot(int) def on_spinbox_num_repeat_value_changed(self, value): self.project_manager.simulator_num_repeat = value @pyqtSlot(int) def on_spinbox_timeout_value_changed(self, value): self.project_manager.simulator_timeout_ms = value @pyqtSlot(int) def on_spinbox_retries_value_changed(self, value): self.project_manager.simulator_retries = value @pyqtSlot(int) def on_combobox_error_handling_index_changed(self, index: int): self.project_manager.simulator_error_handling_index = index @pyqtSlot() def on_message_source_or_destination_updated(self): self.simulator_config.update_active_participants() @pyqtSlot(int, int) def on_table_item_link_clicked(self, row: int, column: int): try: lbl = self.simulator_message_field_model.message_type[row] # type: SimulatorProtocolLabel assert lbl.is_checksum_label assert isinstance(self.active_item, SimulatorMessage) except (IndexError, AssertionError): return d = QDialog(parent=self) layout = QHBoxLayout() layout.addWidget(ChecksumWidget(lbl.label, self.active_item, self.ui.cbViewType.currentIndex())) d.setLayout(layout) d.show() @pyqtSlot(Participant) def on_participant_simulate_changed(self, participant: Participant): self.simulator_scene.refresh_participant(participant) @pyqtSlot() def on_active_participants_updated(self): self.ui.listViewSimulate.model().update() @pyqtSlot(int) def on_edit_label_triggered(self, label_index: int): view_type = self.ui.cbViewType.currentIndex() protocol_label_dialog = ProtocolLabelDialog(message=self.ui.tblViewMessage.selected_message, viewtype=view_type, selected_index=label_index, parent=self) protocol_label_dialog.finished.connect(self.on_protocol_label_dialog_finished) protocol_label_dialog.showMaximized() @pyqtSlot() def on_protocol_label_dialog_finished(self): self.simulator_message_field_model.update() self.simulator_message_table_model.update() self.update_ui() @pyqtSlot(list) def on_files_dropped(self, file_urls: list): for filename in (file_url.toLocalFile() for file_url in file_urls if file_url.isLocalFile()): self.load_simulator_file(filename)