def on_btn_send_clicked(self): try: modulated_data = self.modulate_data() dialog = SendRecvDialogController(self.project_manager.frequency, self.project_manager.sample_rate, self.project_manager.bandwidth, self.project_manager.gain, self.project_manager.device, Mode.send, modulated_data=modulated_data, parent=self) if dialog.has_empty_device_list: Errors.no_device() dialog.close() return elif PluginManager().is_plugin_enabled( "NetworkSDRInterface") and dialog.ui.cbDevice.count() == 1: Errors.network_sdr_send_is_elsewhere() dialog.close() return dialog.recording_parameters.connect( self.project_manager.set_recording_parameters) dialog.show() dialog.graphics_view.show_full_scene(reinitialize=True) except Exception as e: Errors.generic_error(self.tr("Failed to generate data"), str(e), traceback.format_exc()) self.unsetCursor()
def get_devices_for_combobox(self): items = [] for device_name in self.backend_handler.DEVICE_NAMES: dev = self.backend_handler.device_backends[device_name.lower()] if self.is_tx and dev.is_enabled and dev.supports_tx: items.append(device_name) elif self.is_rx and dev.is_enabled and dev.supports_rx: items.append(device_name) if PluginManager().is_plugin_enabled("NetworkSDRInterface"): items.append(NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) return items
def test_plugins_tab(self): self.dialog.ui.tabWidget.setCurrentIndex(4) self.assertEqual(self.dialog.ui.tabWidget.tabText(4), "Plugins") list_view = self.dialog.plugin_controller.ui.listViewPlugins model = list_view.model() self.assertIsInstance(model, PluginListModel) self.assertEqual(model.rowCount(), len(PluginManager().installed_plugins)) for i in range(model.rowCount()): descr = self.dialog.plugin_controller.ui.txtEditPluginDescription.toPlainText( ) list_view.setCurrentIndex(model.index(i, 0)) self.assertNotEqual( descr, self.dialog.plugin_controller.ui.txtEditPluginDescription. toPlainText())
def set_rfcat_button_visibility(self): is_plugin_enabled = PluginManager().is_plugin_enabled("RfCat") self.ui.btnRfCatSend.setVisible(is_plugin_enabled)
def set_network_sdr_send_button_visibility(self): is_plugin_enabled = PluginManager().is_plugin_enabled( "NetworkSDRInterface") self.ui.btnNetworkSDRSend.setVisible(is_plugin_enabled)
def __init__(self, *args): super().__init__(*args) self.ui = Ui_MainWindow() self.ui.setupUi(self) OptionsController.write_default_options() self.project_save_timer = QTimer() self.project_manager = ProjectManager(self) self.plugin_manager = PluginManager() self.signal_tab_controller = SignalTabController( self.project_manager, parent=self.ui.tab_interpretation) self.ui.tab_interpretation.layout().addWidget( self.signal_tab_controller) self.compare_frame_controller = CompareFrameController( parent=self.ui.tab_protocol, plugin_manager=self.plugin_manager, project_manager=self.project_manager) self.ui.tab_protocol.layout().addWidget(self.compare_frame_controller) self.generator_tab_controller = GeneratorTabController( self.compare_frame_controller, self.project_manager, parent=self.ui.tab_generator) self.undo_group = QUndoGroup() self.undo_group.addStack(self.signal_tab_controller.signal_undo_stack) self.undo_group.addStack( self.compare_frame_controller.protocol_undo_stack) self.undo_group.addStack( self.generator_tab_controller.generator_undo_stack) self.undo_group.setActiveStack( self.signal_tab_controller.signal_undo_stack) self.ui.progressBar.hide() self.participant_legend_model = ParticipantLegendListModel( self.project_manager.participants) self.ui.listViewParticipants.setModel(self.participant_legend_model) gtc = self.generator_tab_controller gtc.ui.splitter.setSizes([gtc.width() / 0.7, gtc.width() / 0.3]) self.ui.tab_generator.layout().addWidget(self.generator_tab_controller) self.signal_protocol_dict = {} """:type: dict[SignalFrameController,ProtocolAnalyzer]""" self.signal_tab_controller.ui.lLoadingFile.setText("") self.ui.lnEdtTreeFilter.setClearButtonEnabled(True) group = QActionGroup(self) self.ui.actionFSK.setActionGroup(group) self.ui.actionOOK.setActionGroup(group) self.ui.actionNone.setActionGroup(group) self.ui.actionPSK.setActionGroup(group) self.signal_tab_controller.ui.lShiftStatus.clear() self.recentFileActionList = [] self.create_connects() self.update_recent_action_list() self.filemodel = FileSystemModel(self) path = QDir.homePath() self.filemodel.setIconProvider(FileIconProvider()) self.filemodel.setRootPath(path) self.file_proxy_model = FileFilterProxyModel(self) self.file_proxy_model.setSourceModel(self.filemodel) self.ui.fileTree.setModel(self.file_proxy_model) self.ui.fileTree.setRootIndex( self.file_proxy_model.mapFromSource(self.filemodel.index(path))) self.ui.fileTree.setToolTip(path) self.ui.fileTree.header().setSectionResizeMode(0, QHeaderView.Stretch) self.ui.fileTree.header().setSectionResizeMode(1, QHeaderView.Interactive) self.ui.fileTree.setFocus() self.generator_tab_controller.table_model.cfc = self.compare_frame_controller self.ui.actionConvert_Folder_to_Project.setEnabled(False) undo_action = self.undo_group.createUndoAction(self) undo_action.setIcon(QIcon.fromTheme("edit-undo")) undo_action.setShortcut(QKeySequence.Undo) self.ui.menuEdit.insertAction(self.ui.actionMinimize_all, undo_action) redo_action = self.undo_group.createRedoAction(self) redo_action.setIcon(QIcon.fromTheme("edit-redo")) redo_action.setShortcut(QKeySequence.Redo) self.ui.splitter.setSizes([0, 1]) self.ui.menuEdit.insertAction(self.ui.actionMinimize_all, redo_action) self.refresh_main_menu() self.apply_default_view() self.project_save_timer.start( ProjectManager.AUTOSAVE_INTERVAL_MINUTES * 60 * 1000) self.ui.actionProject_settings.setVisible(False) self.ui.actionSave_project.setVisible(False) # Disabled because never used self.ui.actionMinimize_all.setVisible(False) self.ui.actionMaximize_all.setVisible(False)
def __init__(self, *args): super().__init__(*args) self.ui = Ui_MainWindow() self.ui.setupUi(self) OptionsController.write_default_options() self.project_save_timer = QTimer() self.project_manager = ProjectManager(self) self.plugin_manager = PluginManager() self.signal_tab_controller = SignalTabController( self.project_manager, parent=self.ui.tab_interpretation) self.ui.tab_interpretation.layout().addWidget( self.signal_tab_controller) self.compare_frame_controller = CompareFrameController( parent=self.ui.tab_protocol, plugin_manager=self.plugin_manager, project_manager=self.project_manager) self.compare_frame_controller.ui.splitter.setSizes([1, 1000000]) self.ui.tab_protocol.layout().addWidget(self.compare_frame_controller) self.generator_tab_controller = GeneratorTabController( self.compare_frame_controller, self.project_manager, parent=self.ui.tab_generator) self.undo_group = QUndoGroup() self.undo_group.addStack(self.signal_tab_controller.signal_undo_stack) self.undo_group.addStack( self.compare_frame_controller.protocol_undo_stack) self.undo_group.addStack( self.generator_tab_controller.generator_undo_stack) self.undo_group.setActiveStack( self.signal_tab_controller.signal_undo_stack) self.cancel_action = QAction(self.tr("Cancel"), self) self.cancel_action.setShortcut( QKeySequence.Cancel if hasattr(QKeySequence, "Cancel") else "Esc") self.cancel_action.triggered.connect(self.on_cancel_triggered) self.cancel_action.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.cancel_action.setIcon(QIcon.fromTheme("dialog-cancel")) self.addAction(self.cancel_action) self.participant_legend_model = ParticipantLegendListModel( self.project_manager.participants) self.ui.listViewParticipants.setModel(self.participant_legend_model) gtc = self.generator_tab_controller gtc.ui.splitter.setSizes([gtc.width() / 0.7, gtc.width() / 0.3]) self.ui.tab_generator.layout().addWidget(self.generator_tab_controller) self.signal_protocol_dict = { } # type: dict[SignalFrameController, ProtocolAnalyzer] self.ui.lnEdtTreeFilter.setClearButtonEnabled(True) group = QActionGroup(self) self.ui.actionFSK.setActionGroup(group) self.ui.actionOOK.setActionGroup(group) self.ui.actionNone.setActionGroup(group) self.ui.actionPSK.setActionGroup(group) self.recentFileActionList = [] self.create_connects() self.init_recent_file_action_list( constants.SETTINGS.value("recentFiles", [])) self.filemodel = FileSystemModel(self) path = QDir.homePath() self.filemodel.setIconProvider(FileIconProvider()) self.filemodel.setRootPath(path) self.file_proxy_model = FileFilterProxyModel(self) self.file_proxy_model.setSourceModel(self.filemodel) self.ui.fileTree.setModel(self.file_proxy_model) self.ui.fileTree.setRootIndex( self.file_proxy_model.mapFromSource(self.filemodel.index(path))) self.ui.fileTree.setToolTip(path) self.ui.fileTree.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.ui.fileTree.header().setSectionResizeMode(1, QHeaderView.Stretch) self.ui.fileTree.setFocus() self.generator_tab_controller.table_model.cfc = self.compare_frame_controller self.ui.actionConvert_Folder_to_Project.setEnabled(False) undo_action = self.undo_group.createUndoAction(self) undo_action.setIcon(QIcon.fromTheme("edit-undo")) undo_action.setShortcut(QKeySequence.Undo) self.ui.menuEdit.insertAction(self.ui.actionDecoding, undo_action) redo_action = self.undo_group.createRedoAction(self) redo_action.setIcon(QIcon.fromTheme("edit-redo")) redo_action.setShortcut(QKeySequence.Redo) self.ui.menuEdit.insertAction(self.ui.actionDecoding, redo_action) self.ui.menuEdit.insertSeparator(self.ui.actionDecoding) self.ui.actionAbout_Qt.setIcon( QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png")) self.ui.splitter.setSizes([0, 1]) self.refresh_main_menu() self.apply_default_view( constants.SETTINGS.value('default_view', type=int)) self.project_save_timer.start( ProjectManager.AUTOSAVE_INTERVAL_MINUTES * 60 * 1000) self.ui.actionProject_settings.setVisible(False) self.ui.actionSave_project.setVisible(False)
def create_context_menu(self): self.paste_position = int( self.mapToScene(self.context_menu_position).x()) menu = QMenu(self) if self.save_enabled: menu.addAction(self.save_action) menu.addAction(self.save_as_action) menu.addSeparator() menu.addAction(self.copy_action) self.copy_action.setEnabled(not self.selection_area.is_empty) menu.addAction(self.paste_action) self.paste_action.setEnabled(self.stored_item is not None) menu.addSeparator() if PluginManager().is_plugin_enabled("InsertSine"): menu.addAction(self.insert_sine_action) if not self.selection_area.is_empty: menu.addSeparator() menu.addAction(self.zoom_in_action) menu.addAction(self.zoom_out_action) if not self.selection_area.is_empty: zoom_action = menu.addAction(self.tr("Zoom selection")) zoom_action.setIcon(QIcon.fromTheme("zoom-fit-best")) zoom_action.triggered.connect(self.on_zoom_action_triggered) menu.addSeparator() menu.addAction(self.delete_action) crop_action = menu.addAction(self.tr("Crop to selection")) crop_action.triggered.connect(self.on_crop_action_triggered) mute_action = menu.addAction(self.tr("Mute selection")) mute_action.triggered.connect(self.on_mute_action_triggered) menu.addSeparator() if self.create_new_signal_enabled: create_action = menu.addAction( self.tr("Create signal from selection")) create_action.setIcon(QIcon.fromTheme("document-new")) create_action.triggered.connect( self.on_create_action_triggered) if hasattr(self, "selected_messages"): selected_messages = self.selected_messages else: selected_messages = [] if len(selected_messages) == 1: selected_msg = selected_messages[0] else: selected_msg = None self.participant_actions = {} if len(selected_messages) > 0 and self.participants_assign_enabled: participant_group = QActionGroup(self) participant_menu = menu.addMenu("Participant") none_participant_action = participant_menu.addAction("None") none_participant_action.setCheckable(True) none_participant_action.setActionGroup(participant_group) none_participant_action.triggered.connect( self.on_none_participant_action_triggered) if selected_msg and selected_msg.participant is None: none_participant_action.setChecked(True) for participant in self.participants: pa = participant_menu.addAction(participant.name + " (" + participant.shortname + ")") pa.setCheckable(True) pa.setActionGroup(participant_group) if selected_msg and selected_msg.participant == participant: pa.setChecked(True) self.participant_actions[pa] = participant pa.triggered.connect(self.on_participant_action_triggered) if hasattr(self, "scene_type") and self.scene_type == 0: if not self.selection_area.is_empty: menu.addSeparator() noise_action = menu.addAction( self.tr("Set noise level from Selection")) noise_action.triggered.connect(self.on_noise_action_triggered) menu.addSeparator() menu.addAction(self.undo_action) menu.addAction(self.redo_action) return menu
def contextMenuEvent(self, event: QContextMenuEvent): if self.ctrl_mode: return self.paste_position = int(self.mapToScene(event.pos()).x()) menu = QMenu(self) if self.save_enabled: menu.addAction(self.save_action) menu.addAction(self.save_as_action) menu.addSeparator() zoom_action = None create_action = None noise_action = None crop_action = None mute_action = None menu.addAction(self.copy_action) self.copy_action.setEnabled(not self.selection_area.is_empty) menu.addAction(self.paste_action) self.paste_action.setEnabled(self.stored_item is not None) menu.addSeparator() if PluginManager().is_plugin_enabled("InsertSine"): menu.addAction(self.insert_sine_action) if not self.selection_area.is_empty: menu.addSeparator() if not self.selection_area.is_empty: menu.addAction(self.delete_action) crop_action = menu.addAction(self.tr("Crop to selection")) mute_action = menu.addAction(self.tr("Mute selection")) menu.addSeparator() zoom_action = menu.addAction(self.tr("Zoom selection")) zoom_action.setIcon(QIcon.fromTheme("zoom-in")) if self.create_new_signal_enabled: create_action = menu.addAction(self.tr("Create signal from selection")) create_action.setIcon(QIcon.fromTheme("document-new")) if hasattr(self, "selected_messages"): selected_messages = self.selected_messages else: selected_messages = [] if len(selected_messages) == 1: selected_msg = selected_messages[0] else: selected_msg = None participant_actions = {} if len(selected_messages) > 0 and self.participants_assign_enabled: participant_group = QActionGroup(self) participant_menu = menu.addMenu("Participant") none_participant_action = participant_menu.addAction("None") none_participant_action.setCheckable(True) none_participant_action.setActionGroup(participant_group) if selected_msg and selected_msg.participant is None: none_participant_action.setChecked(True) for participant in self.participants: pa = participant_menu.addAction(participant.name + " (" + participant.shortname + ")") pa.setCheckable(True) pa.setActionGroup(participant_group) if selected_msg and selected_msg.participant == participant: pa.setChecked(True) participant_actions[pa] = participant else: none_participant_action = 42 if hasattr(self, "scene_type") and self.scene_type == 0: if not self.selection_area.is_empty: menu.addSeparator() noise_action = menu.addAction(self.tr("Set noise level from Selection")) menu.addSeparator() menu.addAction(self.undo_action) menu.addAction(self.redo_action) QApplication.processEvents() # without this the menu flickers on first create action = menu.exec_(self.mapToGlobal(event.pos())) if action is None: return elif action == zoom_action: self.zoom_to_selection(self.selection_area.x, self.selection_area.end) elif action == create_action: self.create_clicked.emit(self.selection_area.x, self.selection_area.end) elif action == crop_action: if not self.selection_area.is_empty: crop_action = EditSignalAction(signal=self.signal, protocol=self.protocol, start=self.selection_area.start, end=self.selection_area.end, mode=EditAction.crop, cache_qad=self.cache_qad) self.undo_stack.push(crop_action) elif action == noise_action: self.set_noise_clicked.emit() elif action == mute_action: mute_action = EditSignalAction(signal=self.signal, protocol=self.protocol, start=self.selection_area.start, end=self.selection_area.end, mode=EditAction.mute, cache_qad=self.cache_qad) self.undo_stack.push(mute_action) elif action == none_participant_action: for msg in selected_messages: msg.participant = None self.participant_changed.emit() elif action in participant_actions: for msg in selected_messages: msg.participant = participant_actions[action] self.participant_changed.emit()
def __init__(self, freq, samp_rate, bw, gain, device: str, mode: Mode, modulated_data=None, parent=None): super().__init__(parent) self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.graphics_view = self.ui.graphicsViewSend if mode == Mode.send else self.ui.graphicsViewReceive self.backend_handler = BackendHandler() if mode == Mode.spectrum: self.update_interval = 1 else: self.update_interval = 50 if mode == Mode.send and modulated_data is None: raise ValueError("I need modulated data to send!") if mode == Mode.receive or mode == Mode.spectrum: self.ui.spinBoxNRepeat.hide() self.ui.labelNRepeat.hide() self.ui.lblCurrentRepeatValue.hide() self.ui.lblRepeatText.hide() self.ui.lSamplesSentText.hide() self.ui.progressBar.hide() self.ui.stackedWidget.setCurrentIndex(0) else: self.ui.stackedWidget.setCurrentIndex(1) if mode == Mode.send or mode == Mode.spectrum: self.ui.lSamplesCaptured.hide() self.ui.lSamplesCapturedText.hide() self.ui.lSignalSize.hide() self.ui.lSignalSizeText.hide() self.ui.lTime.hide() self.ui.lTimeText.hide() self.ui.btnSave.hide() if mode == Mode.spectrum: self.setWindowTitle("Spectrum analyzer") if mode == Mode.send: self.ui.btnStart.setIcon(QIcon.fromTheme("media-playback-start")) self.setWindowTitle("Send signal") self.ui.btnStart.setToolTip("Send data") self.ui.btnStop.setToolTip("Stop sending") self.ui.progressBar.setMaximum(len(modulated_data)) self.device_is_sending = False self.ui.btnStop.setEnabled(False) self.ui.btnClear.setEnabled(False) self.ui.btnSave.setEnabled(False) self.start = 0 self.already_saved = True self.bw_sr_are_locked = constants.SETTINGS.value("lock_bandwidth_sample_rate", True, bool) self.ui.spinBoxFreq.setValue(freq) self.ui.spinBoxSampleRate.setValue(samp_rate) self.ui.spinBoxBandwidth.setValue(bw) self.ui.spinBoxGain.setValue(gain) self.ui.spinBoxNRepeat.setValue(constants.SETTINGS.value('num_sending_repeats', 1, type=int)) self.ui.cbDevice.clear() items = [] for device_name in self.backend_handler.DEVICE_NAMES: dev = self.backend_handler.device_backends[device_name.lower()] if mode == Mode.send and dev.is_enabled and dev.supports_tx: items.append(device_name) elif mode in (Mode.receive, Mode.spectrum) and dev.is_enabled and dev.supports_rx: items.append(device_name) if mode == Mode.send and PluginManager().is_plugin_enabled("NetworkSDRInterface"): items.append(NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.ui.cbDevice.addItems(items) if device in items: self.ui.cbDevice.setCurrentIndex(items.index(device)) dev_name = self.ui.cbDevice.currentText() nrep = self.ui.spinBoxNRepeat.value() self.device = VirtualDevice(self.backend_handler, dev_name, mode, bw, freq, gain, samp_rate, samples_to_send=modulated_data, device_ip=self.ui.lineEditIP.text(), sending_repeats=nrep, parent=self) self.ui.lineEditIP.setVisible(dev_name == "USRP") self.ui.labelIP.setVisible(dev_name == "USRP") self.recorded_files = [] self.timer = QTimer(self) if mode == Mode.receive: self.scene_manager = LiveSceneManager(np.array([]), parent=self) # set really in on_device_started elif mode == Mode.send: signal = Signal.from_samples(modulated_data, "Modulated Preview", samp_rate) self.scene_manager = SignalSceneManager(signal, parent=self) self.send_indicator = self.scene_manager.scene.addRect(0, -2, 0, 4, QPen(QColor(Qt.transparent), Qt.FlatCap), QBrush(constants.SEND_INDICATOR_COLOR)) self.send_indicator.stackBefore(self.scene_manager.scene.selection_area) self.scene_manager.init_scene() self.graphics_view.set_signal(signal) self.graphics_view.sample_rate = samp_rate else: self.scene_manager = FFTSceneManager(parent=self, graphic_view=self.graphics_view) self.graphics_view.setScene(self.scene_manager.scene) self.graphics_view.scene_manager = self.scene_manager ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" ipRegex = QRegExp("^" + ipRange + "\\." + ipRange + "\\." + ipRange + "\\." + ipRange + "$") self.ui.lineEditIP.setValidator(QRegExpValidator(ipRegex)) self.create_connects() self.ui.btnLockBWSR.setChecked(self.bw_sr_are_locked) self.on_btn_lock_bw_sr_clicked()
def __init__(self, freq, samp_rate, bw, gain, device, noise, center, bit_length, tolerance, modulation_type_index, parent=None): super().__init__(parent) self.ui = Ui_SniffProtocol() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.ui.spinBoxFreq.setValue(freq) self.ui.spinBoxSampleRate.setValue(samp_rate) self.ui.spinBoxBandwidth.setValue(bw) self.ui.spinBoxGain.setValue(gain) self.ui.spinboxNoise.setValue(noise) self.ui.spinboxCenter.setValue(center) self.ui.spinboxBitLen.setValue(bit_length) self.ui.spinboxErrorTolerance.setValue(tolerance) self.ui.comboxModulation.setCurrentIndex(modulation_type_index) self.ui.btnStop.setEnabled(False) self.ui.btnClear.setEnabled(False) self.ui.cbDevice.clear() items = [] bh = BackendHandler() for device_name in bh.DEVICE_NAMES: dev = bh.device_backends[device_name.lower()] if dev.is_enabled and dev.supports_rx: items.append(device_name) pm = PluginManager() if pm.is_plugin_enabled("NetworkSDRInterface"): items.append(NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.ui.cbDevice.addItems(items) del bh if device in items: self.ui.cbDevice.setCurrentIndex(items.index(device)) if self.ui.cbDevice.count() == 0: Errors.no_device() self.close() return device = self.ui.cbDevice.currentText() self.sniffer = ProtocolSniffer(bit_length, center, noise, tolerance, modulation_type_index, samp_rate, freq, gain, bw, device) self.set_object_visibility() self.sniffer.usrp_ip = self.ui.lineEditIP.text() self.bw_sr_are_locked = self.ui.btnLockBWSR.isChecked() ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" ipRegex = QRegExp("^" + ipRange + "\\." + ipRange + "\\." + ipRange + "\\." + ipRange + "$") self.ui.lineEditIP.setValidator(QRegExpValidator(ipRegex)) # Auto Complete like a Boss completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditOutputFile.setCompleter(completer) self.create_connects()