def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginController(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.labelWindowsError.setVisible(sys.platform == "win32" and platform.architecture()[0] != "64bit") self.ui.checkBoxAlignLabels.setChecked(constants.SETTINGS.value("align_labels", True, bool)) self.ui.checkBoxFallBackTheme.setChecked(constants.SETTINGS.value('use_fallback_theme', False, bool)) self.ui.checkBoxShowConfirmCloseDialog.setChecked(not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', False, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10**6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) for dev_name in self.backend_handler.DEVICE_NAMES: self.ui.listWidgetDevices.addItem(dev_name) self.set_device_enabled_suffix() self.ui.listWidgetDevices.setCurrentRow(0) self.set_gnuradio_status() self.refresh_device_tab() self.create_connects() self.old_symbol_tresh = 10 self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex()
def write_default_options(): settings = constants.SETTINGS keys = settings.allKeys() if 'rel_symbol_length' not in keys: settings.setValue('rel_symbol_length', 0) if 'default_view' not in keys: settings.setValue('default_view', 0) if 'num_sending_repeats' not in keys: settings.setValue('num_sending_repeats', 0) if 'show_pause_as_time' not in keys: settings.setValue('show_pause_as_time', False) settings.sync( ) # Ensure conf dir is created to have field types in place if not os.path.isfile(constants.FIELD_TYPE_SETTINGS): FieldType.save_to_xml(FieldType.default_field_types()) bh = BackendHandler() for be in bh.device_backends.values(): be.write_settings()
def test_protocol_sniffer(self): samples_per_symbol = 100 center = 0.0942 noise = 0.1 tolerance = 2 modulation_type = "FSK" sample_rate = 1e6 device_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME sniffer = ProtocolSniffer(samples_per_symbol=samples_per_symbol, center=center, center_spacing=0.1, noise=noise, tolerance=tolerance, modulation_type=modulation_type, bits_per_symbol=1, device=device_name, backend_handler=BackendHandler(), network_raw_mode=True) port = self.get_free_port() sniffer.rcv_device.set_server_port(port) self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(raw_mode=True) self.network_sdr_plugin_sender.client_port = port sniffer.sniff() QTest.qWait(10) data = ["101010", "000111", "1111000"] pause = 10 * samples_per_symbol modulator = Modulator("test") modulator.samples_per_symbol = samples_per_symbol modulator.sample_rate = sample_rate modulator.modulation_type = modulation_type modulator.parameters[1] = 20e3 modulator.parameters[0] = 10e3 packages = [] for d in data: packages.append(modulator.modulate(list(map(int, d)), pause)) # verify modulation was correct pa = ProtocolAnalyzer(None) signal = Signal("", "", sample_rate=sample_rate) signal.iq_array = IQArray.concatenate(packages) signal.modulation_type = modulation_type signal.samples_per_symbol = samples_per_symbol signal.tolerance = tolerance signal.noise_threshold = noise signal.center = center pa.signal = signal pa.get_protocol_from_signal() self.assertEqual(pa.plain_bits_str, data) # send data send_data = IQArray.concatenate(packages) self.network_sdr_plugin_sender.send_raw_data(send_data, 1) time.sleep(1) # Send enough pauses to end sniffing self.network_sdr_plugin_sender.send_raw_data(IQArray(None, np.float32, 10 * 2 * samples_per_symbol), 1) time.sleep(1) sniffer.stop() self.assertEqual(sniffer.plain_bits_str, data)
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, device: str, testing_mode=False): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_threshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) ProtocolAnalyzer.__init__(self, signal) QObject.__init__(self, None) self.backend_handler = BackendHandler(testing_mode=testing_mode) self.rcv_device = VirtualDevice(self.backend_handler, device, Mode.receive, is_ringbuffer=False, raw_mode=False) self.rcv_device.index_changed.connect(self.on_rcv_thread_index_changed) self.rcv_device.started.connect(self.__emit_started) self.rcv_device.stopped.connect(self.__emit_stopped) self.rel_symbol_len = self._read_symbol_len() self.data_cache = [] self.conseq_non_data = 0 self.reading_data = False self.store_messages = True self.__sniff_file = "" self.__store_data = True
def __init__(self, simulator_config: SimulatorConfiguration, modulators, expression_parser: SimulatorExpressionParser, project_manager: ProjectManager, sniffer: ProtocolSniffer, sender: EndlessSender): super().__init__() self.simulator_config = simulator_config self.project_manager = project_manager self.expression_parser = expression_parser self.modulators = modulators # type: list[Modulator] self.backend_handler = BackendHandler() self.transcript = Transcript() self.current_item = None self.last_sent_message = None self.is_simulating = False self.do_restart = False self.current_repeat = 0 self.log_messages = [] self.sniffer_ready = False self.sender_ready = False self.fatal_device_error_occurred = False self.verbose = True self.sniffer = sniffer self.sender = sender
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, sample_rate: float, freq: float, gain: int, bandwidth: float, device: str, usrp_ip="192.168.10.2"): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_threshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) ProtocolAnalyzer.__init__(self, signal) QObject.__init__(self, None) self.backend_handler = BackendHandler() self.rcv_device = VirtualDevice(self.backend_handler, device, Mode.receive, bandwidth, freq, gain, sample_rate, device_ip=usrp_ip, is_ringbuffer=True) self.rcv_device.index_changed.connect(self.on_rcv_thread_index_changed) self.rcv_device.started.connect(self.__emit_started) self.rcv_device.stopped.connect(self.__emit_stopped) self.rcv_timer = QTimer() self.rcv_timer.setInterval(1000) self.rcv_timer.timeout.connect(self.on_rcv_timer_timeout) self.rel_symbol_len = self._read_symbol_len() self.data_cache = [] self.conseq_non_data = 0 self.reading_data = False self.store_messages = True self.__sniff_file = "" self.__store_data = True
def __init__(self, freq, samp_rate, bw, gain, device: str, parent=None, testing_mode=False): super().__init__(parent) self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.set_sniff_ui_items_visible(False) self.graphics_view = None # type: QGraphicsView self.__device = None # type: VirtualDevice self.backend_handler = BackendHandler(testing_mode=testing_mode) self.ui.btnStop.setEnabled(False) self.ui.btnClear.setEnabled(False) self.ui.btnSave.setEnabled(False) self.start = 0 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 = self.get_devices_for_combobox() self.ui.cbDevice.addItems(items) if device in items: self.ui.cbDevice.setCurrentIndex(items.index(device)) self.timer = QTimer(self) dev_name = self.ui.cbDevice.currentText() self.set_device_ui_items_visible( dev_name != NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.ui.lineEditIP.setVisible(dev_name == "USRP") self.ui.labelIP.setVisible(dev_name == "USRP") ip_range = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" ip_regex = QRegExp("^" + ip_range + "\\." + ip_range + "\\." + ip_range + "\\." + ip_range + "$") self.ui.lineEditIP.setValidator(QRegExpValidator(ip_regex)) self.ui.btnLockBWSR.setChecked(self.bw_sr_are_locked) self.on_btn_lock_bw_sr_clicked()
def on_btn_health_check_clicked(self): info = ExtensionHelper.perform_health_check() info += "\n" + BackendHandler.perform_soundcard_health_check() if util.get_windows_lib_path(): info += "\n\n[INFO] Used DLLs from " + util.get_windows_lib_path() d = util.create_textbox_dialog(info, "Health check for native extensions", self) d.show()
def __init__(self, project_manager: ProjectManager, is_tx: bool, continuous_send_mode=False, parent=None, testing_mode=False): super().__init__(parent) self.is_tx = is_tx self.update_interval = 25 # This flag is needed. Will cause memory leak otherwise. # self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.Window) self.testing_mode = testing_mode self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) self.setFixedSize(QtCore.QSize(1000, 300)) # self.setMaximumSize(QtCore.QSize(500, 500)) util.set_splitter_stylesheet(self.ui.splitter) self.graphics_view = None # type: QGraphicsView self.backend_handler = BackendHandler() self.ui.btnStop.setEnabled(False) # self.ui.btnSave.setEnabled(False) self.start = 0 self.hide_send_ui_items() self.device_settings_widget = DeviceSettingsWidget( project_manager, is_tx, backend_handler=self.backend_handler, continuous_send_mode=continuous_send_mode) self.device_settings_widget.setMaximumSize(500, 300) # self.ui.scrollAreaWidgetContents_2.layout().insertWidget(0, self.device_settings_widget) if testing_mode: self.device_settings_widget.ui.cbDevice.setCurrentText( NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.timer = QTimer(self) try: self.restoreGeometry( constants.SETTINGS.value("{}/geometry".format( self.__class__.__name__))) except TypeError: pass self.ui.splitter.setSizes([0.3 * self.width(), 0.7 * self.width()])
def __init__(self, device_name: str, project_manager: ProjectManager, signal=None, backend_handler=None, network_raw_mode=False, signals=None, parent=None): super().__init__(parent) self.ui = Ui_SniffSettings() self.ui.setupUi(self) signals = signals if signals is not None else [] self.project_manager = project_manager for encoding in self.project_manager.decodings: self.ui.comboBox_sniff_encoding.addItem(encoding.name) self.bootstrap(project_manager.device_conf, signal, enforce_default=True) self.sniffer = ProtocolSniffer( bit_len=self.ui.spinbox_sniff_BitLen.value(), center=self.ui.spinbox_sniff_Center.value(), noise=self.ui.spinbox_sniff_Noise.value(), tolerance=self.ui.spinbox_sniff_ErrorTolerance.value(), modulation_type=self.ui.combox_sniff_Modulation.currentIndex(), device=device_name, backend_handler=BackendHandler() if backend_handler is None else backend_handler, network_raw_mode=network_raw_mode) self.sniffer.adaptive_noise = self.ui.checkBoxAdaptiveNoise.isChecked() self.sniffer.automatic_center = self.ui.checkBoxAutoCenter.isChecked() self.create_connects() self.ui.comboBox_sniff_encoding.currentIndexChanged.emit( self.ui.comboBox_sniff_encoding.currentIndex()) self.ui.comboBox_sniff_viewtype.setCurrentIndex( constants.SETTINGS.value('default_view', 0, int)) # Auto Complete like a Boss completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEdit_sniff_OutputFile.setCompleter(completer) self.signals = signals if len(signals) == 0: self.ui.label_sniff_Signal.hide() self.ui.btn_sniff_use_signal.hide() self.ui.comboBox_sniff_signal.hide() else: for signal in signals: self.ui.comboBox_sniff_signal.addItem(signal.name)
def build_backend_handler_from_args(arguments: argparse.Namespace): from urh.dev.BackendHandler import Backends bh = BackendHandler() if arguments.device_backend == "native": bh.device_backends[arguments.device.lower()].selected_backend = Backends.native elif arguments.device_backend == "gnuradio": bh.device_backends[arguments.device.lower()].selected_backend = Backends.grc else: raise ValueError("Unsupported device backend") return bh
def __init__(self, project_manager: ProjectManager, is_tx: bool, continuous_send_mode=False, parent=None, testing_mode=False): super().__init__(parent) self.is_tx = is_tx self.update_interval = 25 # This flag is needed. Will cause memory leak otherwise. self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.Window) self.testing_mode = testing_mode self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) util.set_splitter_stylesheet(self.ui.splitter) self.ui.txtEditErrors.setFont(util.get_monospace_font()) self.graphics_view = None # type: QGraphicsView self.backend_handler = BackendHandler() self.ui.btnStop.setEnabled(False) self.ui.btnSave.setEnabled(False) self.start = 0 self.device_settings_widget = DeviceSettingsWidget( project_manager, is_tx, backend_handler=self.backend_handler, continuous_send_mode=continuous_send_mode) self.ui.scrollAreaWidgetContents_2.layout().insertWidget( 0, self.device_settings_widget) if testing_mode: self.device_settings_widget.ui.cbDevice.setCurrentText( NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.timer = QTimer(self) self.restoreGeometry( settings.read("{}/geometry".format(self.__class__.__name__), type=bytes)) self.ui.splitter.setSizes( [int(0.4 * self.width()), int(0.6 * self.width())]) self.current_y_slider_value = 1
def on_label_device_missing_info_link_activated(self, link: str): if link == "health_check": info = ExtensionHelper.perform_health_check() info += "\n" + BackendHandler.perform_soundcard_health_check() if util.get_shared_library_path(): if sys.platform == "win32": info += "\n\n[INFO] Used DLLs from " + util.get_shared_library_path() else: info += "\n\n[INFO] Used shared libraries from " + util.get_shared_library_path() d = util.create_textbox_dialog(info, "Health check for native extensions", self) d.show()
def __init__(self, device_name: str, project_manager: ProjectManager, signal=None, backend_handler=None, network_raw_mode=False, real_time=False, parent=None): super().__init__(parent) self.ui = Ui_SniffSettings() self.ui.setupUi(self) conf = project_manager.device_conf bit_length = conf.get("bit_len", signal.bit_len if signal else 100) modulation_type_index = conf.get("modulation_index", signal.modulation_type if signal else 1) tolerance = conf.get("tolerance", signal.tolerance if signal else 5) noise = conf.get("noise", signal.noise_threshold if signal else 0.001) center = conf.get("center", signal.qad_center if signal else 0.02) decoding_name = conf.get("decoding_name", "") self.sniffer = ProtocolSniffer(bit_len=bit_length, center=center, noise=noise, tolerance=tolerance, modulation_type=modulation_type_index, device=device_name, backend_handler=BackendHandler() if backend_handler is None else backend_handler, network_raw_mode=network_raw_mode, real_time=real_time) self.ui.spinbox_sniff_Noise.setValue(noise) self.ui.spinbox_sniff_Center.setValue(center) self.ui.spinbox_sniff_BitLen.setValue(bit_length) self.ui.spinbox_sniff_ErrorTolerance.setValue(tolerance) self.ui.combox_sniff_Modulation.setCurrentIndex(modulation_type_index) self.project_manager = project_manager for encoding in self.project_manager.decodings: self.ui.comboBox_sniff_encoding.addItem(encoding.name) self.create_connects() if decoding_name: self.ui.comboBox_sniff_encoding.setCurrentText(decoding_name) self.ui.comboBox_sniff_viewtype.setCurrentIndex(constants.SETTINGS.value('default_view', 0, int)) # Auto Complete like a Boss completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEdit_sniff_OutputFile.setCompleter(completer)
def __init__(self, project_manager: ProjectManager, is_tx: bool, parent=None, testing_mode=False): super().__init__(parent) self.is_tx = is_tx self.update_interval = 25 self.setWindowFlags(Qt.Window) self.testing_mode = testing_mode self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) self.ui.splitter.setHandleWidth(6) self.graphics_view = None # type: QGraphicsView self.backend_handler = BackendHandler() self.ui.btnStop.setEnabled(False) self.ui.btnClear.setEnabled(False) self.ui.btnSave.setEnabled(False) self.start = 0 self.device_settings_widget = DeviceSettingsWidget( project_manager, is_tx, backend_handler=self.backend_handler) self.ui.scrollAreaWidgetContents_2.layout().insertWidget( 0, self.device_settings_widget) if testing_mode: self.device_settings_widget.ui.cbDevice.setCurrentText( NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.timer = QTimer(self) try: self.restoreGeometry( constants.SETTINGS.value("{}/geometry".format( self.__class__.__name__))) except TypeError: pass self.ui.splitter.setSizes([0.4 * self.width(), 0.6 * self.width()])
def __init__(self, project_manager: ProjectManager, is_tx: bool, backend_handler: BackendHandler = None, continuous_send_mode=False, parent=None): super().__init__(parent) self.ui = Ui_FormDeviceSettings() self.ui.setupUi(self) self.__device = None # type: VirtualDevice self.is_tx = is_tx self.is_rx = not is_tx if backend_handler is None: self.backend_handler = BackendHandler() else: self.backend_handler = backend_handler if self.is_rx: self.ui.spinBoxNRepeat.hide() self.ui.labelNRepeat.hide() else: self.ui.labelDCCorrection.hide() self.ui.checkBoxDCCorrection.hide() self.bw_sr_are_locked = settings.read("lock_bandwidth_sample_rate", True, bool) self.ui.cbDevice.clear() items = self.get_devices_for_combobox(continuous_send_mode) self.ui.cbDevice.addItems(items) self.bootstrap(project_manager.device_conf, enforce_default=True) self.ui.btnLockBWSR.setChecked(self.bw_sr_are_locked) self.on_btn_lock_bw_sr_clicked() ip_range = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" ip_regex = QRegExp("^" + ip_range + "\\." + ip_range + "\\." + ip_range + "\\." + ip_range + "$") self.ui.lineEditIP.setValidator(QRegExpValidator(ip_regex)) self.create_connects() self.sync_gain_sliders()
def record_markered_diapazone(self, my_sel_freq): try: bw = abs(my_sel_freq[1] - my_sel_freq[0]) except: return old_freq = self.device.frequency old_gain = self.device.gain self.on_stop_clicked() self.device = VirtualDevice(BackendHandler(), self.selected_device_name, Mode.receive) self.device.frequency = my_sel_freq[0] + bw / 2 sample_rate = 20e6 self.device.sample_rate = sample_rate self.device.bandwidth = bw self.device.start() time.sleep(0.1) while self.device.data[:self.device. current_index].size < 1 * sample_rate: pass self.device.stop('lol_1') data = self.device.data[:self.device.current_index] dev = self.device big_val = Formatter.big_value_with_suffix timestamp = datetime.now().strftime("%Y-%m-%d_%H:%M:%S") freq = 6800e6 + self.status_k - my_sel_freq[0] + bw / 2 initial_name = "{0}-{1}-{2}Hz-{3}Sps".format(dev.name, timestamp, big_val(freq), big_val(dev.sample_rate)) if dev.bandwidth_is_adjustable: initial_name += "-{}Hz.wav".format(big_val(dev.bandwidth)) initial_name = initial_name.replace( Formatter.local_decimal_seperator(), "_").replace("_000", "") FileOperator.save_data(data, initial_name, sample_rate=sample_rate) self.files_recorded.emit(initial_name) self.init_device() self.device.frequency = old_freq self.device.gain = old_gain self.device.sample_rate = 20e6 self.change_tab.emit()
def __init__(self, project_manager: ProjectManager, is_tx: bool, backend_handler: BackendHandler = None, parent=None): super().__init__(parent) self.ui = Ui_FormDeviceSettings() self.ui.setupUi(self) self.is_tx = is_tx self.is_rx = not is_tx if backend_handler is None: self.backend_handler = BackendHandler() else: self.backend_handler = backend_handler if self.is_rx: self.ui.spinBoxNRepeat.hide() self.ui.labelNRepeat.hide() self.bw_sr_are_locked = constants.SETTINGS.value( "lock_bandwidth_sample_rate", True, bool) self.ui.spinBoxFreq.setValue(project_manager.device_conf["frequency"]) self.ui.spinBoxSampleRate.setValue( project_manager.device_conf["sample_rate"]) self.ui.spinBoxBandwidth.setValue( project_manager.device_conf["bandwidth"]) self.ui.spinBoxGain.setValue( project_manager.device_conf.get("gain", config.DEFAULT_GAIN)) self.ui.spinBoxIFGain.setValue( project_manager.device_conf.get("if_gain", config.DEFAULT_IF_GAIN)) self.ui.spinBoxBasebandGain.setValue( project_manager.device_conf.get("baseband_gain", config.DEFAULT_BB_GAIN)) self.ui.spinBoxFreqCorrection.setValue( project_manager.device_conf.get("freq_correction", config.DEFAULT_FREQ_CORRECTION)) self.ui.spinBoxNRepeat.setValue( constants.SETTINGS.value('num_sending_repeats', 1, type=int)) device = project_manager.device_conf["name"] self.ui.cbDevice.clear() items = self.get_devices_for_combobox() self.ui.cbDevice.addItems(items) if device in items: self.ui.cbDevice.setCurrentIndex(items.index(device)) dev_name = self.ui.cbDevice.currentText() self.set_device_ui_items_visibility(dev_name, adjust_gains=False) self.__device = None # type: VirtualDevice self.ui.btnLockBWSR.setChecked(self.bw_sr_are_locked) self.on_btn_lock_bw_sr_clicked() ip_range = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" ip_regex = QRegExp("^" + ip_range + "\\." + ip_range + "\\." + ip_range + "\\." + ip_range + "$") self.ui.lineEditIP.setValidator(QRegExpValidator(ip_regex)) if "gain" not in project_manager.device_conf: self.set_default_rf_gain() if "if_gain" not in project_manager.device_conf: self.set_default_if_gain() if "baseband_gain" not in project_manager.device_conf: self.set_default_bb_gain() self.create_connects() self.sync_gain_sliders()
def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setWindowFlags(Qt.Window) self.device_options_model = DeviceOptionsTableModel( self.backend_handler, self) self.device_options_model.update() self.ui.tblDevices.setModel(self.device_options_model) self.ui.tblDevices.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.ui.tblDevices.setItemDelegateForColumn( 1, ComboBoxDelegate(["native", "GNU Radio"])) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginFrame(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.btnViewBuildLog.hide() self.build_log = "" # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxTheme.setCurrentIndex( settings.read("theme_index", 0, int)) self.ui.comboBoxIconTheme.setCurrentIndex( settings.read("icon_theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not settings.read('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked( settings.read('hold_shift_to_drag', True, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( settings.read('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxAlignLabels.setChecked( settings.read('align_labels', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue( 100 * settings.read('ram_threshold', 0.6, float)) if self.backend_handler.gr_python_interpreter: self.ui.lineEditGRPythonInterpreter.setText( self.backend_handler.gr_python_interpreter) self.ui.doubleSpinBoxFuzzingPause.setValue( settings.read("default_fuzzing_pause", 10**6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled( settings.read('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxMultipleModulations.setChecked( settings.read("multiple_modulations", False, bool)) self.ui.radioButtonLowModulationAccuracy.setChecked( Modulator.get_dtype() == np.int8) self.ui.radioButtonMediumModulationAccuracy.setChecked( Modulator.get_dtype() == np.int16) self.ui.radioButtonHighModulationAccuracy.setChecked( Modulator.get_dtype() == np.float32) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditGRPythonInterpreter.setCompleter(completer) self.ui.spinBoxFontSize.setValue(qApp.font().pointSize()) self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn( 1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn( 2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.old_num_sending_repeats = self.ui.spinBoxNumSendingRepeats.value() self.ui.labelRebuildNativeStatus.setText("") self.show_available_colormaps() try: self.restoreGeometry( settings.read("{}/geometry".format(self.__class__.__name__))) except TypeError: pass
class OptionsDialog(QDialog): values_changed = pyqtSignal(dict) def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setWindowFlags(Qt.Window) self.device_options_model = DeviceOptionsTableModel( self.backend_handler, self) self.device_options_model.update() self.ui.tblDevices.setModel(self.device_options_model) self.ui.tblDevices.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.ui.tblDevices.setItemDelegateForColumn( 1, ComboBoxDelegate(["native", "GNU Radio"])) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginFrame(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.btnViewBuildLog.hide() self.build_log = "" # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxTheme.setCurrentIndex( settings.read("theme_index", 0, int)) self.ui.comboBoxIconTheme.setCurrentIndex( settings.read("icon_theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not settings.read('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked( settings.read('hold_shift_to_drag', True, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( settings.read('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxAlignLabels.setChecked( settings.read('align_labels', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue( 100 * settings.read('ram_threshold', 0.6, float)) if self.backend_handler.gr_python_interpreter: self.ui.lineEditGRPythonInterpreter.setText( self.backend_handler.gr_python_interpreter) self.ui.doubleSpinBoxFuzzingPause.setValue( settings.read("default_fuzzing_pause", 10**6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled( settings.read('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxMultipleModulations.setChecked( settings.read("multiple_modulations", False, bool)) self.ui.radioButtonLowModulationAccuracy.setChecked( Modulator.get_dtype() == np.int8) self.ui.radioButtonMediumModulationAccuracy.setChecked( Modulator.get_dtype() == np.int16) self.ui.radioButtonHighModulationAccuracy.setChecked( Modulator.get_dtype() == np.float32) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditGRPythonInterpreter.setCompleter(completer) self.ui.spinBoxFontSize.setValue(qApp.font().pointSize()) self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn( 1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn( 2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.old_num_sending_repeats = self.ui.spinBoxNumSendingRepeats.value() self.ui.labelRebuildNativeStatus.setText("") self.show_available_colormaps() try: self.restoreGeometry( settings.read("{}/geometry".format(self.__class__.__name__))) except TypeError: pass def create_connects(self): self.ui.doubleSpinBoxFuzzingPause.valueChanged.connect( self.on_spinbox_fuzzing_pause_value_changed) self.ui.lineEditGRPythonInterpreter.editingFinished.connect( self.on_gr_python_interpreter_path_edited) self.ui.btnChooseGRPythonInterpreter.clicked.connect( self.on_btn_choose_gr_python_interpreter_clicked) self.ui.comboBoxTheme.currentIndexChanged.connect( self.on_combo_box_theme_index_changed) self.ui.checkBoxShowConfirmCloseDialog.clicked.connect( self.on_checkbox_confirm_close_dialog_clicked) self.ui.checkBoxHoldShiftToDrag.clicked.connect( self.on_checkbox_hold_shift_to_drag_clicked) self.ui.checkBoxAlignLabels.clicked.connect( self.on_checkbox_align_labels_clicked) self.ui.checkBoxDefaultFuzzingPause.clicked.connect( self.on_checkbox_default_fuzzing_pause_clicked) self.ui.btnAddLabelType.clicked.connect( self.on_btn_add_label_type_clicked) self.ui.btnRemoveLabeltype.clicked.connect( self.on_btn_remove_label_type_clicked) self.ui.radioButtonLowModulationAccuracy.clicked.connect( self.on_radio_button_low_modulation_accuracy_clicked) self.ui.radioButtonMediumModulationAccuracy.clicked.connect( self.on_radio_button_medium_modulation_accuracy_clicked) self.ui.radioButtonHighModulationAccuracy.clicked.connect( self.on_radio_button_high_modulation_accuracy_clicked) self.ui.doubleSpinBoxRAMThreshold.valueChanged.connect( self.on_double_spinbox_ram_threshold_value_changed) self.ui.btnRebuildNative.clicked.connect( self.on_btn_rebuild_native_clicked) self.ui.comboBoxIconTheme.currentIndexChanged.connect( self.on_combobox_icon_theme_index_changed) self.ui.checkBoxMultipleModulations.clicked.connect( self.on_checkbox_multiple_modulations_clicked) self.ui.btnViewBuildLog.clicked.connect( self.on_btn_view_build_log_clicked) self.ui.labelDeviceMissingInfo.linkActivated.connect( self.on_label_device_missing_info_link_activated) self.ui.spinBoxFontSize.editingFinished.connect( self.on_spin_box_font_size_editing_finished) def show_gnuradio_infos(self): self.ui.lineEditGRPythonInterpreter.setText( self.backend_handler.gr_python_interpreter) if self.backend_handler.gnuradio_is_installed: self.ui.lineEditGRPythonInterpreter.setStyleSheet( "background-color: lightgreen") self.ui.lineEditGRPythonInterpreter.setToolTip( "GNU Radio interface is working.") else: self.ui.lineEditGRPythonInterpreter.setStyleSheet( "background-color: orange") self.ui.lineEditGRPythonInterpreter.setToolTip( "GNU Radio is not installed or incompatible with " "the configured python interpreter.") def read_options(self): self.ui.comboBoxDefaultView.setCurrentIndex( settings.read('default_view', 0, type=int)) self.ui.spinBoxNumSendingRepeats.setValue( settings.read('num_sending_repeats', 0, type=int)) self.ui.checkBoxPauseTime.setChecked( settings.read('show_pause_as_time', False, type=bool)) self.old_show_pause_as_time = bool( self.ui.checkBoxPauseTime.isChecked()) self.field_type_table_model.field_types = FieldType.load_from_xml() self.field_type_table_model.update() def refresh_device_tab(self): self.backend_handler.get_backends() self.show_gnuradio_infos() self.device_options_model.update() def show_available_colormaps(self): height = 50 selected = colormaps.read_selected_colormap_name_from_settings() for colormap_name in sorted(colormaps.maps.keys()): image = Spectrogram.create_colormap_image(colormap_name, height=height) rb = QRadioButton(colormap_name) rb.setObjectName(colormap_name) rb.setChecked(colormap_name == selected) rb.setIcon(QIcon(QPixmap.fromImage(image))) rb.setIconSize(QSize(256, height)) self.ui.scrollAreaWidgetSpectrogramColormapContents.layout( ).addWidget(rb) def closeEvent(self, event: QCloseEvent): changed_values = {} if bool(self.ui.checkBoxPauseTime.isChecked() ) != self.old_show_pause_as_time: changed_values['show_pause_as_time'] = bool( self.ui.checkBoxPauseTime.isChecked()) if self.old_default_view != self.ui.comboBoxDefaultView.currentIndex(): changed_values[ 'default_view'] = self.ui.comboBoxDefaultView.currentIndex() if self.old_num_sending_repeats != self.ui.spinBoxNumSendingRepeats.value( ): changed_values[ "num_sending_repeats"] = self.ui.spinBoxNumSendingRepeats.value( ) settings.write('default_view', self.ui.comboBoxDefaultView.currentIndex()) settings.write('num_sending_repeats', self.ui.spinBoxNumSendingRepeats.value()) settings.write('show_pause_as_time', self.ui.checkBoxPauseTime.isChecked()) FieldType.save_to_xml(self.field_type_table_model.field_types) self.plugin_controller.save_enabled_states() for plugin in self.plugin_controller.model.plugins: plugin.destroy_settings_frame() for i in range(self.ui.scrollAreaWidgetSpectrogramColormapContents. layout().count()): widget = self.ui.scrollAreaWidgetSpectrogramColormapContents.layout( ).itemAt(i).widget() if isinstance(widget, QRadioButton) and widget.isChecked(): selected_colormap_name = widget.objectName() if selected_colormap_name != colormaps.read_selected_colormap_name_from_settings( ): colormaps.choose_colormap(selected_colormap_name) colormaps.write_selected_colormap_to_settings( selected_colormap_name) changed_values[ "spectrogram_colormap"] = selected_colormap_name break self.values_changed.emit(changed_values) settings.write("{}/geometry".format(self.__class__.__name__), self.saveGeometry()) super().closeEvent(event) def set_gnuradio_status(self): self.backend_handler.gr_python_interpreter = self.ui.lineEditGRPythonInterpreter.text( ) self.refresh_device_tab() @pyqtSlot() def on_btn_add_label_type_clicked(self): suffix = 1 field_type_names = { ft.caption for ft in self.field_type_table_model.field_types } while "New Fieldtype #" + str(suffix) in field_type_names: suffix += 1 caption = "New Fieldtype #" + str(suffix) self.field_type_table_model.field_types.append( FieldType(caption, FieldType.Function.CUSTOM)) self.field_type_table_model.update() @pyqtSlot() def on_btn_remove_label_type_clicked(self): if self.field_type_table_model.field_types: selected_indices = { i.row() for i in self.ui.tblLabeltypes.selectedIndexes() } if selected_indices: for i in reversed(sorted(selected_indices)): self.field_type_table_model.field_types.pop(i) else: self.field_type_table_model.field_types.pop() self.field_type_table_model.update() @pyqtSlot() def on_double_spinbox_ram_threshold_value_changed(self): val = self.ui.doubleSpinBoxRAMThreshold.value() settings.write("ram_threshold", val / 100) @pyqtSlot(bool) def on_checkbox_confirm_close_dialog_clicked(self, checked: bool): settings.write("not_show_close_dialog", not checked) @pyqtSlot(int) def on_combo_box_theme_index_changed(self, index: int): settings.write('theme_index', index) @pyqtSlot(int) def on_combobox_icon_theme_index_changed(self, index: int): settings.write('icon_theme_index', index) util.set_icon_theme() @pyqtSlot(bool) def on_checkbox_hold_shift_to_drag_clicked(self, checked: bool): settings.write("hold_shift_to_drag", checked) @pyqtSlot(bool) def on_checkbox_default_fuzzing_pause_clicked(self, checked: bool): settings.write('use_default_fuzzing_pause', checked) self.ui.doubleSpinBoxFuzzingPause.setEnabled(checked) @pyqtSlot(float) def on_spinbox_fuzzing_pause_value_changed(self, value: float): settings.write("default_fuzzing_pause", int(value)) @pyqtSlot() def on_gr_python_interpreter_path_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_btn_choose_gr_python_interpreter_clicked(self): if sys.platform == "win32": dialog_filter = "Executable (*.exe);;All files (*.*)" else: dialog_filter = "" filename, _ = QFileDialog.getOpenFileName( self, self.tr("Choose python interpreter"), filter=dialog_filter) if filename: self.ui.lineEditGRPythonInterpreter.setText(filename) self.set_gnuradio_status() @pyqtSlot(bool) def on_checkbox_align_labels_clicked(self, checked: bool): settings.write("align_labels", checked) @pyqtSlot() def on_btn_rebuild_native_clicked(self): library_dirs = None if not self.ui.lineEditLibDirs.text() \ else list(map(str.strip, self.ui.lineEditLibDirs.text().split(","))) include_dirs = None if not self.ui.lineEditIncludeDirs.text() \ else list(map(str.strip, self.ui.lineEditIncludeDirs.text().split(","))) extensions, _ = ExtensionHelper.get_device_extensions_and_extras( library_dirs=library_dirs, include_dirs=include_dirs) self.ui.labelRebuildNativeStatus.setText( self.tr("Rebuilding device extensions...")) QApplication.instance().processEvents() build_cmd = [ sys.executable, os.path.realpath(ExtensionHelper.__file__), "build_ext", "--inplace", "-t", tempfile.gettempdir() ] if library_dirs: build_cmd.extend(["-L", ":".join(library_dirs)]) if include_dirs: build_cmd.extend(["-I", ":".join(include_dirs)]) subprocess.call([ sys.executable, os.path.realpath(ExtensionHelper.__file__), "clean", "--all" ]) p = subprocess.Popen(build_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) num_dots = 1 while p.poll() is None: self.ui.labelRebuildNativeStatus.setText( self.tr("Rebuilding device extensions" + ". " * num_dots)) QApplication.instance().processEvents() time.sleep(0.1) num_dots %= 10 num_dots += 1 rc = p.returncode if rc == 0: self.ui.labelRebuildNativeStatus.setText( self.tr("<font color=green>" "Rebuilt {0} device extensions. " "</font>" "Please restart URH.".format(len(extensions)))) else: self.ui.labelRebuildNativeStatus.setText( self.tr("<font color='red'>" "Failed to rebuild {0} device extensions. " "</font>" "Run URH as root (<b>sudo urh</b>) " "and try again.".format(len(extensions)))) self.build_log = p.stdout.read().decode() self.ui.btnViewBuildLog.show() @pyqtSlot() def on_checkbox_multiple_modulations_clicked(self): settings.write("multiple_modulations", self.ui.checkBoxMultipleModulations.isChecked()) @pyqtSlot() def on_btn_view_build_log_clicked(self): if not self.build_log: return dialog = util.create_textbox_dialog(self.build_log, "Build log", parent=self) dialog.show() @pyqtSlot(str) def on_label_device_missing_info_link_activated(self, link: str): if link == "health_check": info = ExtensionHelper.perform_health_check() info += "\n" + BackendHandler.perform_soundcard_health_check() if util.get_shared_library_path(): if sys.platform == "win32": info += "\n\n[INFO] Used DLLs from " + util.get_shared_library_path( ) else: info += "\n\n[INFO] Used shared libraries from " + util.get_shared_library_path( ) d = util.create_textbox_dialog( info, "Health check for native extensions", self) d.show() @pyqtSlot() def on_spin_box_font_size_editing_finished(self): settings.write("font_size", self.ui.spinBoxFontSize.value()) font = qApp.font() font.setPointSize(self.ui.spinBoxFontSize.value()) qApp.setFont(font) @pyqtSlot(bool) def on_radio_button_high_modulation_accuracy_clicked(self, checked): if checked: settings.write("modulation_dtype", "float32") @pyqtSlot(bool) def on_radio_button_medium_modulation_accuracy_clicked(self, checked): if checked: settings.write("modulation_dtype", "int16") @pyqtSlot(bool) def on_radio_button_low_modulation_accuracy_clicked(self, checked): if checked: settings.write("modulation_dtype", "int8") @staticmethod def write_default_options(): keys = settings.all_keys() if 'default_view' not in keys: settings.write('default_view', 0) if 'num_sending_repeats' not in keys: settings.write('num_sending_repeats', 0) if 'show_pause_as_time' not in keys: settings.write('show_pause_as_time', False) settings.sync( ) # Ensure conf dir is created to have field types in place if not os.path.isfile(settings.FIELD_TYPE_SETTINGS): FieldType.save_to_xml(FieldType.default_field_types()) bh = BackendHandler() for be in bh.device_backends.values(): be.write_settings()
def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginController(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelWindowsError.setVisible(sys.platform == "win32" and platform.architecture()[0] != "64bit") self.ui.comboBoxTheme.setCurrentIndex(constants.SETTINGS.value("theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', False, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue(100 * constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10 ** 6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) for dev_name in self.backend_handler.DEVICE_NAMES: self.ui.listWidgetDevices.addItem(dev_name) self.set_device_enabled_suffix() self.ui.listWidgetDevices.setCurrentRow(0) self.set_gnuradio_status() self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.ui.labelRebuildNativeStatus.setText("") try: self.restoreGeometry(constants.SETTINGS.value("{}/geometry".format(self.__class__.__name__))) except TypeError: pass
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 OptionsController(QDialog): values_changed = pyqtSignal(dict) def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginController(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.labelWindowsError.setVisible(sys.platform == "win32" and platform.architecture()[0] != "64bit") self.ui.checkBoxAlignLabels.setChecked(constants.SETTINGS.value("align_labels", True, bool)) self.ui.checkBoxFallBackTheme.setChecked(constants.SETTINGS.value('use_fallback_theme', False, bool)) self.ui.checkBoxShowConfirmCloseDialog.setChecked(not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', False, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue(100*constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10**6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) for dev_name in self.backend_handler.DEVICE_NAMES: self.ui.listWidgetDevices.addItem(dev_name) self.set_device_enabled_suffix() self.ui.listWidgetDevices.setCurrentRow(0) self.set_gnuradio_status() self.refresh_device_tab() self.create_connects() self.old_symbol_tresh = 10 self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() @property def selected_device(self) -> BackendContainer: try: devname = self.ui.listWidgetDevices.currentItem().text().lower() dev_key = self.__get_key_from_device_display_text(devname) return self.backend_handler.device_backends[dev_key] except: return "" def __get_key_from_device_display_text(self, displayed_device_name): displayed_device_name = displayed_device_name.lower() for key in self.backend_handler.DEVICE_NAMES: key = key.lower() if displayed_device_name.startswith(key): return key return None def create_connects(self): self.ui.spinBoxSymbolTreshold.valueChanged.connect(self.on_spinbox_symbol_threshold_value_changed) self.ui.doubleSpinBoxFuzzingPause.valueChanged.connect(self.on_spinbox_fuzzing_pause_value_changed) self.ui.chkBoxEnableSymbols.clicked.connect(self.on_chkbox_enable_symbols_clicked) self.ui.lineEditPython2Interpreter.editingFinished.connect(self.on_python2_exe_path_edited) self.ui.lineEditGnuradioDirectory.editingFinished.connect(self.on_gnuradio_install_dir_edited) self.ui.listWidgetDevices.currentRowChanged.connect(self.on_list_widget_devices_current_row_changed) self.ui.chkBoxDeviceEnabled.clicked.connect(self.on_chk_box_device_enabled_clicked) self.ui.rbGnuradioBackend.clicked.connect(self.on_rb_gnuradio_backend_clicked) self.ui.rbNativeBackend.clicked.connect(self.on_rb_native_backend_clicked) self.ui.checkBoxFallBackTheme.clicked.connect(self.on_checkbox_fallback_theme_clicked) self.ui.checkBoxShowConfirmCloseDialog.clicked.connect(self.on_checkbox_confirm_close_dialog_clicked) self.ui.checkBoxHoldShiftToDrag.clicked.connect(self.on_checkbox_hold_shift_to_drag_clicked) self.ui.checkBoxAlignLabels.clicked.connect(self.on_checkbox_align_labels_clicked) self.ui.checkBoxDefaultFuzzingPause.clicked.connect(self.on_checkbox_default_fuzzing_pause_clicked) self.ui.btnAddLabelType.clicked.connect(self.on_btn_add_label_type_clicked) self.ui.btnRemoveLabeltype.clicked.connect(self.on_btn_remove_label_type_clicked) self.ui.radioButtonPython2Interpreter.clicked.connect(self.on_radio_button_python2_interpreter_clicked) self.ui.radioButtonGnuradioDirectory.clicked.connect(self.on_radio_button_gnuradio_directory_clicked) self.ui.doubleSpinBoxRAMThreshold.valueChanged.connect(self.on_double_spinbox_ram_threshold_value_changed) def show_gnuradio_infos(self): self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.gnuradio_installed: self.ui.lGnuradioInstalled.setStyleSheet("") self.ui.lGnuradioInstalled.setText(self.tr("Gnuradio interface is working.")) else: self.ui.lGnuradioInstalled.setStyleSheet("color: red") self.ui.lGnuradioInstalled.setText( self.tr("Gnuradio is not installed or incompatible with python2 interpreter.")) def show_selected_device_params(self): if self.ui.listWidgetDevices.currentRow() >= 0: dev = self.selected_device self.ui.chkBoxDeviceEnabled.setEnabled(len(dev.avail_backends) > 0) self.ui.rbGnuradioBackend.setEnabled(dev.has_gnuradio_backend) self.ui.rbNativeBackend.setEnabled(dev.has_native_backend) self.ui.chkBoxDeviceEnabled.setChecked(dev.is_enabled) self.ui.rbGnuradioBackend.setChecked(dev.selected_backend == Backends.grc) self.ui.rbNativeBackend.setChecked(dev.selected_backend == Backends.native) if dev.supports_tx and dev.supports_rx: self.ui.lSupport.setText(self.tr("device supports sending and receiving")) self.ui.lSupport.setStyleSheet("color: green") elif dev.supports_rx and not dev.supports_tx: self.ui.lSupport.setText(self.tr("device supports receiving only")) self.ui.lSupport.setStyleSheet("color: blue") elif not dev.supports_rx and dev.supports_tx: self.ui.lSupport.setText(self.tr("device supports sending only")) self.ui.lSupport.setStyleSheet("color: blue") else: self.ui.lSupport.setText(self.tr("device supports neither sending nor receiving")) self.ui.lSupport.setStyleSheet("color: red") def set_device_enabled_suffix(self): for i in range(self.ui.listWidgetDevices.count()): w = self.ui.listWidgetDevices.item(i) dev_key = self.__get_key_from_device_display_text(w.text()) is_enabled = self.backend_handler.device_backends[dev_key].is_enabled suffix = self.tr("enabled") if is_enabled else self.tr("disabled") dev_name = next(dn for dn in BackendHandler.DEVICE_NAMES if dn.lower() == dev_key) w.setText("{0} - {1}".format(dev_name, suffix)) def read_options(self): settings = constants.SETTINGS # self.ui.chkBoxUSRP.setChecked(settings.value('usrp_available', type=bool)) # self.ui.chkBoxHackRF.setChecked(settings.value('hackrf_available', type=bool)) self.ui.comboBoxDefaultView.setCurrentIndex(settings.value('default_view', type=int)) self.ui.spinBoxNumSendingRepeats.setValue(settings.value('num_sending_repeats', type=int)) self.ui.checkBoxPauseTime.setChecked(settings.value('show_pause_as_time', type=bool)) symbol_thresh = (settings.value('rel_symbol_length', type=int) - 100) / (-2) self.ui.spinBoxSymbolTreshold.setValue(symbol_thresh) self.old_symbol_tresh = symbol_thresh self.old_show_pause_as_time = bool(self.ui.checkBoxPauseTime.isChecked()) self.field_type_table_model.field_types = FieldType.load_from_xml() self.field_type_table_model.update() def refresh_device_tab(self): self.backend_handler.get_backends() self.show_gnuradio_infos() self.show_selected_device_params() self.set_device_enabled_suffix() self.ui.lineEditGnuradioDirectory.setEnabled(self.backend_handler.use_gnuradio_install_dir) self.ui.lineEditPython2Interpreter.setDisabled(self.backend_handler.use_gnuradio_install_dir) def closeEvent(self, event: QCloseEvent): changed_values = {} if self.ui.spinBoxSymbolTreshold.value() != self.old_symbol_tresh: changed_values["rel_symbol_length"] = 100 - 2 * self.ui.spinBoxSymbolTreshold.value() if bool(self.ui.checkBoxPauseTime.isChecked()) != self.old_show_pause_as_time: changed_values['show_pause_as_time'] = bool(self.ui.checkBoxPauseTime.isChecked()) if self.old_default_view != self.ui.comboBoxDefaultView.currentIndex(): changed_values['default_view'] = self.ui.comboBoxDefaultView.currentIndex() settings = constants.SETTINGS settings.setValue('default_view', self.ui.comboBoxDefaultView.currentIndex()) settings.setValue('num_sending_repeats', self.ui.spinBoxNumSendingRepeats.value()) settings.setValue('show_pause_as_time', self.ui.checkBoxPauseTime.isChecked()) FieldType.save_to_xml(self.field_type_table_model.field_types) self.plugin_controller.save_enabled_states() self.values_changed.emit(changed_values) event.accept() def set_gnuradio_status(self): self.backend_handler.python2_exe = self.ui.lineEditPython2Interpreter.text() self.backend_handler.gnuradio_install_dir = self.ui.lineEditGnuradioDirectory.text() self.backend_handler.use_gnuradio_install_dir = self.ui.radioButtonGnuradioDirectory.isChecked() self.backend_handler.set_gnuradio_installed_status() constants.SETTINGS.setValue("use_gnuradio_install_dir", self.backend_handler.use_gnuradio_install_dir) self.refresh_device_tab() @pyqtSlot() def on_btn_add_label_type_clicked(self): suffix = 1 field_type_names = {ft.caption for ft in self.field_type_table_model.field_types} while "New Fieldtype #" + str(suffix) in field_type_names: suffix += 1 caption = "New Fieldtype #" + str(suffix) self.field_type_table_model.field_types.append(FieldType(caption, FieldType.Function.CUSTOM)) self.field_type_table_model.update() @pyqtSlot() def on_btn_remove_label_type_clicked(self): if self.field_type_table_model.field_types: selected_indices = {i.row() for i in self.ui.tblLabeltypes.selectedIndexes()} if selected_indices: for i in reversed(sorted(selected_indices)): self.field_type_table_model.field_types.pop(i) else: self.field_type_table_model.field_types.pop() self.field_type_table_model.update() @pyqtSlot() def on_spinbox_symbol_threshold_value_changed(self): val = self.ui.spinBoxSymbolTreshold.value() self.ui.lSymbolLength.setText(str(100 - 2 * val) + "%") if val == 50: txt = self.tr("No symbols will be created") self.ui.chkBoxEnableSymbols.setChecked(False) elif val == 0: txt = self.tr("A symbol will be created in any case") self.ui.chkBoxEnableSymbols.setChecked(True) else: self.ui.chkBoxEnableSymbols.setChecked(True) bit_len = 1000 rel_val = val / 100 rel_symbol_len = (100 - 2 * val) / 100 txt = self.tr( "Custom symbols will be created outside {0:d}%-{1:d}% of selected bit length.\n\n" "Example - With bit length {2:d} following will hold: \n" "{3:d} - {4:d}: \tSymbol A\n" "{5:d} - {6:d}: \tStandard symbol (0 or 1)\n" "{7:d} - {8:d}: \tSymbol B\n" "{9:d} - {10:d}: \tStandard symbol (0 or 1)\n\n" "Note there will be different symbols for various signal levels (e.g. low and high).".format( 100 - val, 100 + val, bit_len, int((1 - rel_val) * bit_len - rel_symbol_len * bit_len), int((1 - rel_val) * bit_len), int((1 - rel_val) * bit_len), int((1 + rel_val) * bit_len), int((1 + rel_val) * bit_len), int((1 + rel_val) * bit_len + rel_symbol_len * bit_len), int((2 - rel_val) * bit_len), int((2 + rel_val) * bit_len))) self.ui.lExplanation.setText(txt) @pyqtSlot() def on_double_spinbox_ram_threshold_value_changed(self): val = self.ui.doubleSpinBoxRAMThreshold.value() constants.SETTINGS.setValue("ram_threshold", val / 100) @pyqtSlot(bool) def on_checkbox_fallback_theme_clicked(self, use_fallback: bool): constants.SETTINGS.setValue('use_fallback_theme', use_fallback) if use_fallback: QApplication.setStyle(QStyleFactory.create("Fusion")) else: QApplication.setStyle(constants.SETTINGS.value("default_theme", type=str)) @pyqtSlot(bool) def on_checkbox_confirm_close_dialog_clicked(self, checked: bool): constants.SETTINGS.setValue("not_show_close_dialog", not checked) @pyqtSlot(bool) def on_checkbox_hold_shift_to_drag_clicked(self, checked: bool): constants.SETTINGS.setValue("hold_shift_to_drag", checked) @pyqtSlot(bool) def on_checkbox_default_fuzzing_pause_clicked(self, checked: bool): constants.SETTINGS.setValue('use_default_fuzzing_pause', checked) self.ui.doubleSpinBoxFuzzingPause.setEnabled(checked) @pyqtSlot(float) def on_spinbox_fuzzing_pause_value_changed(self, value: float): constants.SETTINGS.setValue("default_fuzzing_pause", int(value)) @pyqtSlot() def on_python2_exe_path_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_chk_box_device_enabled_clicked(self): self.selected_device.is_enabled = bool(self.ui.chkBoxDeviceEnabled.isChecked()) self.selected_device.write_settings() self.set_device_enabled_suffix() @pyqtSlot() def on_rb_gnuradio_backend_clicked(self): if Backends.grc in self.selected_device.avail_backends: self.selected_device.selected_backend = Backends.grc self.selected_device.write_settings() @pyqtSlot() def on_rb_native_backend_clicked(self): if Backends.native in self.selected_device.avail_backends: self.selected_device.selected_backend = Backends.native self.selected_device.write_settings() @pyqtSlot(bool) def on_chkbox_enable_symbols_clicked(self, checked: bool): if checked: self.ui.spinBoxSymbolTreshold.setValue(10) else: self.ui.spinBoxSymbolTreshold.setValue(50) @pyqtSlot(bool) def on_checkbox_align_labels_clicked(self, checked: bool): constants.SETTINGS.setValue("align_labels", checked) @pyqtSlot(int) def on_list_widget_devices_current_row_changed(self, current_row: int): self.show_selected_device_params() @pyqtSlot(bool) def on_radio_button_gnuradio_directory_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot(bool) def on_radio_button_python2_interpreter_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot() def on_gnuradio_install_dir_edited(self): self.set_gnuradio_status() @staticmethod def write_default_options(): settings = constants.SETTINGS keys = settings.allKeys() if not 'rel_symbol_length' in keys: settings.setValue('rel_symbol_length', 0) if not 'default_view' in keys: settings.setValue('default_view', 0) if not 'num_sending_repeats' in keys: settings.setValue('num_sending_repeats', 0) if not 'show_pause_as_time' in keys: settings.setValue('show_pause_as_time', False) settings.sync() # Ensure conf dir is created to have field types in place if not os.path.isfile(constants.FIELD_TYPE_SETTINGS): FieldType.save_to_xml(FieldType.default_field_types()) bh = BackendHandler() for be in bh.device_backends.values(): be.write_settings()
class OptionsDialog(QDialog): values_changed = pyqtSignal(dict) def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.backend_handler.set_gnuradio_installed_status() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setWindowFlags(Qt.Window) self.device_options_model = DeviceOptionsTableModel(self.backend_handler, self) self.device_options_model.update() self.ui.tblDevices.setModel(self.device_options_model) self.ui.tblDevices.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblDevices.setItemDelegateForColumn(1, ComboBoxDelegate(["native", "GNU Radio"])) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginFrame(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.btnViewBuildLog.hide() self.build_log = "" # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxTheme.setCurrentIndex(constants.SETTINGS.value("theme_index", 0, int)) self.ui.comboBoxIconTheme.setCurrentIndex(constants.SETTINGS.value("icon_theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', True, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxAlignLabels.setChecked(constants.SETTINGS.value('align_labels', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue(100 * constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10 ** 6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxMultipleModulations.setChecked(constants.SETTINGS.value("multiple_modulations", False, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) self.ui.spinBoxFontSize.setValue(qApp.font().pointSize()) self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.old_num_sending_repeats = self.ui.spinBoxNumSendingRepeats.value() self.ui.labelRebuildNativeStatus.setText("") self.show_available_colormaps() try: self.restoreGeometry(constants.SETTINGS.value("{}/geometry".format(self.__class__.__name__))) except TypeError: pass def create_connects(self): self.ui.doubleSpinBoxFuzzingPause.valueChanged.connect(self.on_spinbox_fuzzing_pause_value_changed) self.ui.lineEditPython2Interpreter.editingFinished.connect(self.on_python2_exe_path_edited) self.ui.btnChoosePython2Interpreter.clicked.connect(self.on_btn_choose_python2_interpreter_clicked) self.ui.btnChooseGnuRadioDirectory.clicked.connect(self.on_btn_choose_gnuradio_directory_clicked) self.ui.lineEditGnuradioDirectory.editingFinished.connect(self.on_gnuradio_install_dir_edited) self.ui.comboBoxTheme.currentIndexChanged.connect(self.on_combo_box_theme_index_changed) self.ui.checkBoxShowConfirmCloseDialog.clicked.connect(self.on_checkbox_confirm_close_dialog_clicked) self.ui.checkBoxHoldShiftToDrag.clicked.connect(self.on_checkbox_hold_shift_to_drag_clicked) self.ui.checkBoxAlignLabels.clicked.connect(self.on_checkbox_align_labels_clicked) self.ui.checkBoxDefaultFuzzingPause.clicked.connect(self.on_checkbox_default_fuzzing_pause_clicked) self.ui.btnAddLabelType.clicked.connect(self.on_btn_add_label_type_clicked) self.ui.btnRemoveLabeltype.clicked.connect(self.on_btn_remove_label_type_clicked) self.ui.radioButtonPython2Interpreter.clicked.connect(self.on_radio_button_python2_interpreter_clicked) self.ui.radioButtonGnuradioDirectory.clicked.connect(self.on_radio_button_gnuradio_directory_clicked) self.ui.doubleSpinBoxRAMThreshold.valueChanged.connect(self.on_double_spinbox_ram_threshold_value_changed) self.ui.btnRebuildNative.clicked.connect(self.on_btn_rebuild_native_clicked) self.ui.comboBoxIconTheme.currentIndexChanged.connect(self.on_combobox_icon_theme_index_changed) self.ui.checkBoxMultipleModulations.clicked.connect(self.on_checkbox_multiple_modulations_clicked) self.ui.btnViewBuildLog.clicked.connect(self.on_btn_view_build_log_clicked) self.ui.labelDeviceMissingInfo.linkActivated.connect(self.on_label_device_missing_info_link_activated) self.ui.spinBoxFontSize.editingFinished.connect(self.on_spin_box_font_size_editing_finished) def show_gnuradio_infos(self): self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.gnuradio_is_installed: self.ui.lGnuradioInstalled.setStyleSheet("") self.ui.lGnuradioInstalled.setText(self.tr("Gnuradio interface is working.")) else: self.ui.lGnuradioInstalled.setStyleSheet("color: red") self.ui.lGnuradioInstalled.setText( self.tr("Gnuradio is not installed or incompatible with python2 interpreter.")) def read_options(self): settings = constants.SETTINGS self.ui.comboBoxDefaultView.setCurrentIndex(settings.value('default_view', type=int)) self.ui.spinBoxNumSendingRepeats.setValue(settings.value('num_sending_repeats', type=int)) self.ui.checkBoxPauseTime.setChecked(settings.value('show_pause_as_time', type=bool)) self.old_show_pause_as_time = bool(self.ui.checkBoxPauseTime.isChecked()) self.field_type_table_model.field_types = FieldType.load_from_xml() self.field_type_table_model.update() def refresh_device_tab(self): self.backend_handler.get_backends() self.show_gnuradio_infos() self.device_options_model.update() self.ui.lineEditGnuradioDirectory.setEnabled(self.backend_handler.use_gnuradio_install_dir) self.ui.lineEditPython2Interpreter.setDisabled(self.backend_handler.use_gnuradio_install_dir) def show_available_colormaps(self): height = 50 selected = colormaps.read_selected_colormap_name_from_settings() for colormap_name in sorted(colormaps.maps.keys()): image = Spectrogram.create_colormap_image(colormap_name, height=height) rb = QRadioButton(colormap_name) rb.setObjectName(colormap_name) rb.setChecked(colormap_name == selected) rb.setIcon(QIcon(QPixmap.fromImage(image))) rb.setIconSize(QSize(256, height)) self.ui.scrollAreaWidgetSpectrogramColormapContents.layout().addWidget(rb) def closeEvent(self, event: QCloseEvent): changed_values = {} if bool(self.ui.checkBoxPauseTime.isChecked()) != self.old_show_pause_as_time: changed_values['show_pause_as_time'] = bool(self.ui.checkBoxPauseTime.isChecked()) if self.old_default_view != self.ui.comboBoxDefaultView.currentIndex(): changed_values['default_view'] = self.ui.comboBoxDefaultView.currentIndex() if self.old_num_sending_repeats != self.ui.spinBoxNumSendingRepeats.value(): changed_values["num_sending_repeats"] = self.ui.spinBoxNumSendingRepeats.value() settings = constants.SETTINGS settings.setValue('default_view', self.ui.comboBoxDefaultView.currentIndex()) settings.setValue('num_sending_repeats', self.ui.spinBoxNumSendingRepeats.value()) settings.setValue('show_pause_as_time', self.ui.checkBoxPauseTime.isChecked()) FieldType.save_to_xml(self.field_type_table_model.field_types) self.plugin_controller.save_enabled_states() for plugin in self.plugin_controller.model.plugins: plugin.destroy_settings_frame() for i in range(self.ui.scrollAreaWidgetSpectrogramColormapContents.layout().count()): widget = self.ui.scrollAreaWidgetSpectrogramColormapContents.layout().itemAt(i).widget() if isinstance(widget, QRadioButton) and widget.isChecked(): selected_colormap_name = widget.objectName() if selected_colormap_name != colormaps.read_selected_colormap_name_from_settings(): colormaps.choose_colormap(selected_colormap_name) colormaps.write_selected_colormap_to_settings(selected_colormap_name) changed_values["spectrogram_colormap"] = selected_colormap_name break self.values_changed.emit(changed_values) constants.SETTINGS.setValue("{}/geometry".format(self.__class__.__name__), self.saveGeometry()) super().closeEvent(event) def set_gnuradio_status(self): self.backend_handler.python2_exe = self.ui.lineEditPython2Interpreter.text() self.backend_handler.gnuradio_install_dir = self.ui.lineEditGnuradioDirectory.text() constants.SETTINGS.setValue("gnuradio_install_dir", self.ui.lineEditGnuradioDirectory.text()) self.backend_handler.use_gnuradio_install_dir = self.ui.radioButtonGnuradioDirectory.isChecked() self.backend_handler.set_gnuradio_installed_status() constants.SETTINGS.setValue("use_gnuradio_install_dir", self.backend_handler.use_gnuradio_install_dir) self.refresh_device_tab() @pyqtSlot() def on_btn_add_label_type_clicked(self): suffix = 1 field_type_names = {ft.caption for ft in self.field_type_table_model.field_types} while "New Fieldtype #" + str(suffix) in field_type_names: suffix += 1 caption = "New Fieldtype #" + str(suffix) self.field_type_table_model.field_types.append(FieldType(caption, FieldType.Function.CUSTOM)) self.field_type_table_model.update() @pyqtSlot() def on_btn_remove_label_type_clicked(self): if self.field_type_table_model.field_types: selected_indices = {i.row() for i in self.ui.tblLabeltypes.selectedIndexes()} if selected_indices: for i in reversed(sorted(selected_indices)): self.field_type_table_model.field_types.pop(i) else: self.field_type_table_model.field_types.pop() self.field_type_table_model.update() @pyqtSlot() def on_double_spinbox_ram_threshold_value_changed(self): val = self.ui.doubleSpinBoxRAMThreshold.value() constants.SETTINGS.setValue("ram_threshold", val / 100) @pyqtSlot(bool) def on_checkbox_confirm_close_dialog_clicked(self, checked: bool): constants.SETTINGS.setValue("not_show_close_dialog", not checked) @pyqtSlot(int) def on_combo_box_theme_index_changed(self, index: int): constants.SETTINGS.setValue('theme_index', index) @pyqtSlot(int) def on_combobox_icon_theme_index_changed(self, index: int): constants.SETTINGS.setValue('icon_theme_index', index) util.set_icon_theme() @pyqtSlot(bool) def on_checkbox_hold_shift_to_drag_clicked(self, checked: bool): constants.SETTINGS.setValue("hold_shift_to_drag", checked) @pyqtSlot(bool) def on_checkbox_default_fuzzing_pause_clicked(self, checked: bool): constants.SETTINGS.setValue('use_default_fuzzing_pause', checked) self.ui.doubleSpinBoxFuzzingPause.setEnabled(checked) @pyqtSlot(float) def on_spinbox_fuzzing_pause_value_changed(self, value: float): constants.SETTINGS.setValue("default_fuzzing_pause", int(value)) @pyqtSlot() def on_python2_exe_path_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_btn_choose_python2_interpreter_clicked(self): if sys.platform == "win32": dialog_filter = "Executable (*.exe);;All files (*.*)" else: dialog_filter = "" filename, _ = QFileDialog.getOpenFileName(self, self.tr("Choose python2 interpreter"), filter=dialog_filter) if filename: self.ui.lineEditPython2Interpreter.setText(filename) self.set_gnuradio_status() @pyqtSlot() def on_btn_choose_gnuradio_directory_clicked(self): directory = QFileDialog.getExistingDirectory(self, "Choose GNU Radio directory") if directory: self.ui.lineEditGnuradioDirectory.setText(directory) self.set_gnuradio_status() @pyqtSlot(bool) def on_checkbox_align_labels_clicked(self, checked: bool): constants.SETTINGS.setValue("align_labels", checked) @pyqtSlot(bool) def on_radio_button_gnuradio_directory_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot(bool) def on_radio_button_python2_interpreter_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot() def on_gnuradio_install_dir_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_btn_rebuild_native_clicked(self): library_dirs = None if not self.ui.lineEditLibDirs.text() \ else list(map(str.strip, self.ui.lineEditLibDirs.text().split(","))) extensions, _ = ExtensionHelper.get_device_extensions_and_extras(library_dirs=library_dirs) self.ui.labelRebuildNativeStatus.setText(self.tr("Rebuilding device extensions...")) QApplication.instance().processEvents() build_cmd = [sys.executable, os.path.realpath(ExtensionHelper.__file__), "build_ext", "--inplace", "-t", tempfile.gettempdir()] if library_dirs: build_cmd.extend(["-L", ":".join(library_dirs)]) subprocess.call([sys.executable, os.path.realpath(ExtensionHelper.__file__), "clean", "--all"]) p = subprocess.Popen(build_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) num_dots = 1 while p.poll() is None: self.ui.labelRebuildNativeStatus.setText(self.tr("Rebuilding device extensions" + ". " * num_dots)) QApplication.instance().processEvents() time.sleep(0.1) num_dots %= 10 num_dots += 1 rc = p.returncode if rc == 0: self.ui.labelRebuildNativeStatus.setText(self.tr("<font color=green>" "Rebuilt {0} device extensions. " "</font>" "Please restart URH.".format(len(extensions)))) else: self.ui.labelRebuildNativeStatus.setText(self.tr("<font color='red'>" "Failed to rebuild {0} device extensions. " "</font>" "Run URH as root (<b>sudo urh</b>) " "and try again.".format(len(extensions)))) self.build_log = p.stdout.read().decode() self.ui.btnViewBuildLog.show() @pyqtSlot() def on_checkbox_multiple_modulations_clicked(self): constants.SETTINGS.setValue("multiple_modulations", self.ui.checkBoxMultipleModulations.isChecked()) @pyqtSlot() def on_btn_view_build_log_clicked(self): if not self.build_log: return dialog = util.create_textbox_dialog(self.build_log, "Build log", parent=self) dialog.show() @pyqtSlot(str) def on_label_device_missing_info_link_activated(self, link: str): if link == "health_check": info = ExtensionHelper.perform_health_check() info += "\n" + BackendHandler.perform_soundcard_health_check() if util.get_shared_library_path(): if sys.platform == "win32": info += "\n\n[INFO] Used DLLs from " + util.get_shared_library_path() else: info += "\n\n[INFO] Used shared libraries from " + util.get_shared_library_path() d = util.create_textbox_dialog(info, "Health check for native extensions", self) d.show() @pyqtSlot() def on_spin_box_font_size_editing_finished(self): constants.SETTINGS.setValue("font_size", self.ui.spinBoxFontSize.value()) font = qApp.font() font.setPointSize(self.ui.spinBoxFontSize.value()) qApp.setFont(font) @staticmethod def write_default_options(): settings = constants.SETTINGS keys = settings.allKeys() if 'default_view' not in keys: settings.setValue('default_view', 0) if 'num_sending_repeats' not in keys: settings.setValue('num_sending_repeats', 0) if 'show_pause_as_time' not in keys: settings.setValue('show_pause_as_time', False) settings.sync() # Ensure conf dir is created to have field types in place if not os.path.isfile(constants.FIELD_TYPE_SETTINGS): FieldType.save_to_xml(FieldType.default_field_types()) bh = BackendHandler() for be in bh.device_backends.values(): be.write_settings()
class OptionsDialog(QDialog): values_changed = pyqtSignal(dict) def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginFrame(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.btnViewBuildLog.hide() self.build_log = "" # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelWindowsError.setVisible(sys.platform == "win32" and platform.architecture()[0] != "64bit") self.ui.labelIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxTheme.setCurrentIndex(constants.SETTINGS.value("theme_index", 0, int)) self.ui.comboBoxIconTheme.setCurrentIndex(constants.SETTINGS.value("icon_theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', True, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxAlignLabels.setChecked(constants.SETTINGS.value('align_labels', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue(100 * constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10 ** 6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxMultipleModulations.setChecked(constants.SETTINGS.value("multiple_modulations", False, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) for dev_name in self.backend_handler.DEVICE_NAMES: self.ui.listWidgetDevices.addItem(dev_name) self.set_device_status() self.ui.listWidgetDevices.setCurrentRow(0) self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.old_num_sending_repeats = self.ui.spinBoxNumSendingRepeats.value() self.ui.labelRebuildNativeStatus.setText("") self.show_available_colormaps() try: self.restoreGeometry(constants.SETTINGS.value("{}/geometry".format(self.__class__.__name__))) except TypeError: pass @property def selected_device(self) -> BackendContainer: try: devname = self.ui.listWidgetDevices.currentItem().text().lower() dev_key = self.__get_key_from_device_display_text(devname) return self.backend_handler.device_backends[dev_key] except: return "" def __get_key_from_device_display_text(self, displayed_device_name): displayed_device_name = displayed_device_name.lower() for key in self.backend_handler.DEVICE_NAMES: key = key.lower() if displayed_device_name.startswith(key): return key return None def create_connects(self): self.ui.doubleSpinBoxFuzzingPause.valueChanged.connect(self.on_spinbox_fuzzing_pause_value_changed) self.ui.lineEditPython2Interpreter.editingFinished.connect(self.on_python2_exe_path_edited) self.ui.btnChoosePython2Interpreter.clicked.connect(self.on_btn_choose_python2_interpreter_clicked) self.ui.btnChooseGnuRadioDirectory.clicked.connect(self.on_btn_choose_gnuradio_directory_clicked) self.ui.lineEditGnuradioDirectory.editingFinished.connect(self.on_gnuradio_install_dir_edited) self.ui.listWidgetDevices.currentRowChanged.connect(self.on_list_widget_devices_current_row_changed) self.ui.chkBoxDeviceEnabled.clicked.connect(self.on_chk_box_device_enabled_clicked) self.ui.rbGnuradioBackend.clicked.connect(self.on_rb_gnuradio_backend_clicked) self.ui.rbNativeBackend.clicked.connect(self.on_rb_native_backend_clicked) self.ui.comboBoxTheme.currentIndexChanged.connect(self.on_combo_box_theme_index_changed) self.ui.checkBoxShowConfirmCloseDialog.clicked.connect(self.on_checkbox_confirm_close_dialog_clicked) self.ui.checkBoxHoldShiftToDrag.clicked.connect(self.on_checkbox_hold_shift_to_drag_clicked) self.ui.checkBoxAlignLabels.clicked.connect(self.on_checkbox_align_labels_clicked) self.ui.checkBoxDefaultFuzzingPause.clicked.connect(self.on_checkbox_default_fuzzing_pause_clicked) self.ui.btnAddLabelType.clicked.connect(self.on_btn_add_label_type_clicked) self.ui.btnRemoveLabeltype.clicked.connect(self.on_btn_remove_label_type_clicked) self.ui.radioButtonPython2Interpreter.clicked.connect(self.on_radio_button_python2_interpreter_clicked) self.ui.radioButtonGnuradioDirectory.clicked.connect(self.on_radio_button_gnuradio_directory_clicked) self.ui.doubleSpinBoxRAMThreshold.valueChanged.connect(self.on_double_spinbox_ram_threshold_value_changed) self.ui.btnRebuildNative.clicked.connect(self.on_btn_rebuild_native_clicked) self.ui.btnHealthCheck.clicked.connect(self.on_btn_health_check_clicked) self.ui.comboBoxIconTheme.currentIndexChanged.connect(self.on_combobox_icon_theme_index_changed) self.ui.checkBoxMultipleModulations.clicked.connect(self.on_checkbox_multiple_modulations_clicked) self.ui.btnViewBuildLog.clicked.connect(self.on_btn_view_build_log_clicked) def show_gnuradio_infos(self): self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.gnuradio_is_installed: self.ui.lGnuradioInstalled.setStyleSheet("") self.ui.lGnuradioInstalled.setText(self.tr("Gnuradio interface is working.")) else: self.ui.lGnuradioInstalled.setStyleSheet("color: red") self.ui.lGnuradioInstalled.setText( self.tr("Gnuradio is not installed or incompatible with python2 interpreter.")) def show_selected_device_params(self): if self.ui.listWidgetDevices.currentRow() >= 0: dev = self.selected_device self.ui.chkBoxDeviceEnabled.setEnabled(len(dev.avail_backends) > 0) self.ui.rbGnuradioBackend.setEnabled(dev.has_gnuradio_backend) self.ui.rbNativeBackend.setEnabled(dev.has_native_backend) self.ui.chkBoxDeviceEnabled.setChecked(dev.is_enabled) self.ui.rbGnuradioBackend.setChecked(dev.selected_backend == Backends.grc) self.ui.rbNativeBackend.setChecked(dev.selected_backend == Backends.native) if dev.supports_tx and dev.supports_rx: self.ui.lSupport.setText(self.tr("device supports sending and receiving")) self.ui.lSupport.setStyleSheet("color: green") elif dev.supports_rx and not dev.supports_tx: self.ui.lSupport.setText(self.tr("device supports receiving only")) self.ui.lSupport.setStyleSheet("color: blue") elif not dev.supports_rx and dev.supports_tx: self.ui.lSupport.setText(self.tr("device supports sending only")) self.ui.lSupport.setStyleSheet("color: blue") else: self.ui.lSupport.setText(self.tr("device supports neither sending nor receiving")) self.ui.lSupport.setStyleSheet("color: red") def set_device_status(self): for i in range(self.ui.listWidgetDevices.count()): w = self.ui.listWidgetDevices.item(i) dev_key = self.__get_key_from_device_display_text(w.text()) is_enabled = self.backend_handler.device_backends[dev_key].is_enabled selected_backend = self.backend_handler.device_backends[dev_key].selected_backend.value suffix = self.tr("enabled") if is_enabled else self.tr("disabled") dev_name = next(dn for dn in BackendHandler.DEVICE_NAMES if dn.lower() == dev_key) w.setText("{0}\t ({2})\t {1}".format(dev_name, suffix, selected_backend)) def read_options(self): settings = constants.SETTINGS self.ui.comboBoxDefaultView.setCurrentIndex(settings.value('default_view', type=int)) self.ui.spinBoxNumSendingRepeats.setValue(settings.value('num_sending_repeats', type=int)) self.ui.checkBoxPauseTime.setChecked(settings.value('show_pause_as_time', type=bool)) self.old_show_pause_as_time = bool(self.ui.checkBoxPauseTime.isChecked()) self.field_type_table_model.field_types = FieldType.load_from_xml() self.field_type_table_model.update() def refresh_device_tab(self): self.backend_handler.get_backends() self.show_gnuradio_infos() self.show_selected_device_params() self.set_device_status() self.ui.lineEditGnuradioDirectory.setEnabled(self.backend_handler.use_gnuradio_install_dir) self.ui.lineEditPython2Interpreter.setDisabled(self.backend_handler.use_gnuradio_install_dir) def show_available_colormaps(self): height = 50 selected = colormaps.read_selected_colormap_name_from_settings() for colormap_name in sorted(colormaps.maps.keys()): image = Spectrogram.create_colormap_image(colormap_name, height=height) rb = QRadioButton(colormap_name) rb.setObjectName(colormap_name) rb.setChecked(colormap_name == selected) rb.setIcon(QIcon(QPixmap.fromImage(image))) rb.setIconSize(QSize(256, height)) self.ui.scrollAreaWidgetSpectrogramColormapContents.layout().addWidget(rb) def closeEvent(self, event: QCloseEvent): changed_values = {} if bool(self.ui.checkBoxPauseTime.isChecked()) != self.old_show_pause_as_time: changed_values['show_pause_as_time'] = bool(self.ui.checkBoxPauseTime.isChecked()) if self.old_default_view != self.ui.comboBoxDefaultView.currentIndex(): changed_values['default_view'] = self.ui.comboBoxDefaultView.currentIndex() if self.old_num_sending_repeats != self.ui.spinBoxNumSendingRepeats.value(): changed_values["num_sending_repeats"] = self.ui.spinBoxNumSendingRepeats.value() settings = constants.SETTINGS settings.setValue('default_view', self.ui.comboBoxDefaultView.currentIndex()) settings.setValue('num_sending_repeats', self.ui.spinBoxNumSendingRepeats.value()) settings.setValue('show_pause_as_time', self.ui.checkBoxPauseTime.isChecked()) FieldType.save_to_xml(self.field_type_table_model.field_types) self.plugin_controller.save_enabled_states() for plugin in self.plugin_controller.model.plugins: plugin.destroy_settings_frame() for i in range(self.ui.scrollAreaWidgetSpectrogramColormapContents.layout().count()): widget = self.ui.scrollAreaWidgetSpectrogramColormapContents.layout().itemAt(i).widget() if isinstance(widget, QRadioButton) and widget.isChecked(): selected_colormap_name = widget.objectName() if selected_colormap_name != colormaps.read_selected_colormap_name_from_settings(): colormaps.choose_colormap(selected_colormap_name) colormaps.write_selected_colormap_to_settings(selected_colormap_name) changed_values["spectrogram_colormap"] = selected_colormap_name break self.values_changed.emit(changed_values) constants.SETTINGS.setValue("{}/geometry".format(self.__class__.__name__), self.saveGeometry()) super().closeEvent(event) def set_gnuradio_status(self): self.backend_handler.python2_exe = self.ui.lineEditPython2Interpreter.text() constants.SETTINGS.setValue("python2_exe", self.ui.lineEditPython2Interpreter.text()) self.backend_handler.gnuradio_install_dir = self.ui.lineEditGnuradioDirectory.text() constants.SETTINGS.setValue("gnuradio_install_dir", self.ui.lineEditGnuradioDirectory.text()) self.backend_handler.use_gnuradio_install_dir = self.ui.radioButtonGnuradioDirectory.isChecked() self.backend_handler.set_gnuradio_installed_status() constants.SETTINGS.setValue("use_gnuradio_install_dir", self.backend_handler.use_gnuradio_install_dir) self.refresh_device_tab() @pyqtSlot() def on_btn_add_label_type_clicked(self): suffix = 1 field_type_names = {ft.caption for ft in self.field_type_table_model.field_types} while "New Fieldtype #" + str(suffix) in field_type_names: suffix += 1 caption = "New Fieldtype #" + str(suffix) self.field_type_table_model.field_types.append(FieldType(caption, FieldType.Function.CUSTOM)) self.field_type_table_model.update() @pyqtSlot() def on_btn_remove_label_type_clicked(self): if self.field_type_table_model.field_types: selected_indices = {i.row() for i in self.ui.tblLabeltypes.selectedIndexes()} if selected_indices: for i in reversed(sorted(selected_indices)): self.field_type_table_model.field_types.pop(i) else: self.field_type_table_model.field_types.pop() self.field_type_table_model.update() @pyqtSlot() def on_double_spinbox_ram_threshold_value_changed(self): val = self.ui.doubleSpinBoxRAMThreshold.value() constants.SETTINGS.setValue("ram_threshold", val / 100) @pyqtSlot(bool) def on_checkbox_confirm_close_dialog_clicked(self, checked: bool): constants.SETTINGS.setValue("not_show_close_dialog", not checked) @pyqtSlot(int) def on_combo_box_theme_index_changed(self, index: int): constants.SETTINGS.setValue('theme_index', index) if index > 0: QApplication.instance().setStyle(QStyleFactory.create("Fusion")) else: QApplication.instance().setStyle(constants.SETTINGS.value("default_theme", type=str)) @pyqtSlot(int) def on_combobox_icon_theme_index_changed(self, index: int): constants.SETTINGS.setValue('icon_theme_index', index) util.set_icon_theme() @pyqtSlot(bool) def on_checkbox_hold_shift_to_drag_clicked(self, checked: bool): constants.SETTINGS.setValue("hold_shift_to_drag", checked) @pyqtSlot(bool) def on_checkbox_default_fuzzing_pause_clicked(self, checked: bool): constants.SETTINGS.setValue('use_default_fuzzing_pause', checked) self.ui.doubleSpinBoxFuzzingPause.setEnabled(checked) @pyqtSlot(float) def on_spinbox_fuzzing_pause_value_changed(self, value: float): constants.SETTINGS.setValue("default_fuzzing_pause", int(value)) @pyqtSlot() def on_python2_exe_path_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_btn_choose_python2_interpreter_clicked(self): if sys.platform == "win32": dialog_filter = "Executable (*.exe);;All files (*.*)" else: dialog_filter = "" filename, _ = QFileDialog.getOpenFileName(self, self.tr("Choose python2 interpreter"), filter=dialog_filter) if filename: self.ui.lineEditPython2Interpreter.setText(filename) self.set_gnuradio_status() @pyqtSlot() def on_btn_choose_gnuradio_directory_clicked(self): directory = QFileDialog.getExistingDirectory(self, "Choose GNU Radio directory") if directory: self.ui.lineEditGnuradioDirectory.setText(directory) self.set_gnuradio_status() @pyqtSlot() def on_chk_box_device_enabled_clicked(self): self.selected_device.is_enabled = bool(self.ui.chkBoxDeviceEnabled.isChecked()) self.selected_device.write_settings() self.set_device_status() @pyqtSlot() def on_rb_gnuradio_backend_clicked(self): if Backends.grc in self.selected_device.avail_backends: self.ui.rbGnuradioBackend.setChecked(True) self.selected_device.selected_backend = Backends.grc self.selected_device.write_settings() self.set_device_status() @pyqtSlot() def on_rb_native_backend_clicked(self): if Backends.native in self.selected_device.avail_backends: self.ui.rbNativeBackend.setChecked(True) self.selected_device.selected_backend = Backends.native self.selected_device.write_settings() self.set_device_status() @pyqtSlot(bool) def on_checkbox_align_labels_clicked(self, checked: bool): constants.SETTINGS.setValue("align_labels", checked) @pyqtSlot(int) def on_list_widget_devices_current_row_changed(self, current_row: int): self.show_selected_device_params() @pyqtSlot(bool) def on_radio_button_gnuradio_directory_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot(bool) def on_radio_button_python2_interpreter_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot() def on_gnuradio_install_dir_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_btn_rebuild_native_clicked(self): library_dirs = None if not self.ui.lineEditLibDirs.text() \ else list(map(str.strip, self.ui.lineEditLibDirs.text().split(","))) extensions = ExtensionHelper.get_device_extensions(use_cython=False, library_dirs=library_dirs) self.ui.labelRebuildNativeStatus.setText(self.tr("Rebuilding device extensions...")) QApplication.instance().processEvents() build_cmd = [sys.executable, os.path.realpath(ExtensionHelper.__file__), "build_ext", "--inplace", "-t", tempfile.gettempdir()] if library_dirs: build_cmd.extend(["-L", ":".join(library_dirs)]) subprocess.call([sys.executable, os.path.realpath(ExtensionHelper.__file__), "clean", "--all"]) p = subprocess.Popen(build_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) num_dots = 1 while p.poll() is None: self.ui.labelRebuildNativeStatus.setText(self.tr("Rebuilding device extensions" + ". " * num_dots)) QApplication.instance().processEvents() time.sleep(0.1) num_dots %= 10 num_dots += 1 rc = p.returncode if rc == 0: self.ui.labelRebuildNativeStatus.setText(self.tr("<font color=green>" "Rebuilt {0} device extensions. " "</font>" "Please restart URH.".format(len(extensions)))) else: self.ui.labelRebuildNativeStatus.setText(self.tr("<font color='red'>" "Failed to rebuild {0} device extensions. " "</font>" "Run URH as root (<b>sudo urh</b>) " "and try again.".format(len(extensions)))) self.build_log = p.stdout.read().decode() self.ui.btnViewBuildLog.show() @pyqtSlot() def on_btn_health_check_clicked(self): info = ExtensionHelper.perform_health_check() info += "\n" + BackendHandler.perform_soundcard_health_check() if util.get_windows_lib_path(): info += "\n\n[INFO] Used DLLs from " + util.get_windows_lib_path() d = util.create_textbox_dialog(info, "Health check for native extensions", self) d.show() @pyqtSlot() def on_checkbox_multiple_modulations_clicked(self): constants.SETTINGS.setValue("multiple_modulations", self.ui.checkBoxMultipleModulations.isChecked()) @pyqtSlot() def on_btn_view_build_log_clicked(self): if not self.build_log: return dialog = util.create_textbox_dialog(self.build_log, "Build log", parent=self) dialog.show() @staticmethod def write_default_options(): settings = constants.SETTINGS keys = settings.allKeys() if 'default_view' not in keys: settings.setValue('default_view', 0) if 'num_sending_repeats' not in keys: settings.setValue('num_sending_repeats', 0) if 'show_pause_as_time' not in keys: settings.setValue('show_pause_as_time', False) settings.sync() # Ensure conf dir is created to have field types in place if not os.path.isfile(constants.FIELD_TYPE_SETTINGS): FieldType.save_to_xml(FieldType.default_field_types()) bh = BackendHandler() for be in bh.device_backends.values(): be.write_settings()
class OptionsController(QDialog): values_changed = pyqtSignal(dict) def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginController(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelWindowsError.setVisible( sys.platform == "win32" and platform.architecture()[0] != "64bit") self.ui.comboBoxTheme.setCurrentIndex( constants.SETTINGS.value("theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked( constants.SETTINGS.value('hold_shift_to_drag', False, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue( 100 * constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked( self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked( not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText( self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText( self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue( constants.SETTINGS.value("default_fuzzing_pause", 10**6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) for dev_name in self.backend_handler.DEVICE_NAMES: self.ui.listWidgetDevices.addItem(dev_name) self.set_device_enabled_suffix() self.ui.listWidgetDevices.setCurrentRow(0) self.set_gnuradio_status() self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn( 1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn( 2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.ui.labelRebuildNativeStatus.setText("") try: self.restoreGeometry( constants.SETTINGS.value("{}/geometry".format( self.__class__.__name__))) except TypeError: pass @property def selected_device(self) -> BackendContainer: try: devname = self.ui.listWidgetDevices.currentItem().text().lower() dev_key = self.__get_key_from_device_display_text(devname) return self.backend_handler.device_backends[dev_key] except: return "" def __get_key_from_device_display_text(self, displayed_device_name): displayed_device_name = displayed_device_name.lower() for key in self.backend_handler.DEVICE_NAMES: key = key.lower() if displayed_device_name.startswith(key): return key return None def create_connects(self): self.ui.doubleSpinBoxFuzzingPause.valueChanged.connect( self.on_spinbox_fuzzing_pause_value_changed) self.ui.lineEditPython2Interpreter.editingFinished.connect( self.on_python2_exe_path_edited) self.ui.lineEditGnuradioDirectory.editingFinished.connect( self.on_gnuradio_install_dir_edited) self.ui.listWidgetDevices.currentRowChanged.connect( self.on_list_widget_devices_current_row_changed) self.ui.chkBoxDeviceEnabled.clicked.connect( self.on_chk_box_device_enabled_clicked) self.ui.rbGnuradioBackend.clicked.connect( self.on_rb_gnuradio_backend_clicked) self.ui.rbNativeBackend.clicked.connect( self.on_rb_native_backend_clicked) self.ui.comboBoxTheme.currentIndexChanged.connect( self.on_combo_box_theme_index_changed) self.ui.checkBoxShowConfirmCloseDialog.clicked.connect( self.on_checkbox_confirm_close_dialog_clicked) self.ui.checkBoxHoldShiftToDrag.clicked.connect( self.on_checkbox_hold_shift_to_drag_clicked) self.ui.checkBoxAlignLabels.clicked.connect( self.on_checkbox_align_labels_clicked) self.ui.checkBoxDefaultFuzzingPause.clicked.connect( self.on_checkbox_default_fuzzing_pause_clicked) self.ui.btnAddLabelType.clicked.connect( self.on_btn_add_label_type_clicked) self.ui.btnRemoveLabeltype.clicked.connect( self.on_btn_remove_label_type_clicked) self.ui.radioButtonPython2Interpreter.clicked.connect( self.on_radio_button_python2_interpreter_clicked) self.ui.radioButtonGnuradioDirectory.clicked.connect( self.on_radio_button_gnuradio_directory_clicked) self.ui.doubleSpinBoxRAMThreshold.valueChanged.connect( self.on_double_spinbox_ram_threshold_value_changed) self.ui.btnRebuildNative.clicked.connect( self.on_btn_rebuild_native_clicked) def show_gnuradio_infos(self): self.ui.lineEditPython2Interpreter.setText( self.backend_handler.python2_exe) self.ui.lineEditGnuradioDirectory.setText( self.backend_handler.gnuradio_install_dir) if self.backend_handler.gnuradio_installed: self.ui.lGnuradioInstalled.setStyleSheet("") self.ui.lGnuradioInstalled.setText( self.tr("Gnuradio interface is working.")) else: self.ui.lGnuradioInstalled.setStyleSheet("color: red") self.ui.lGnuradioInstalled.setText( self. tr("Gnuradio is not installed or incompatible with python2 interpreter." )) def show_selected_device_params(self): if self.ui.listWidgetDevices.currentRow() >= 0: dev = self.selected_device self.ui.chkBoxDeviceEnabled.setEnabled(len(dev.avail_backends) > 0) self.ui.rbGnuradioBackend.setEnabled(dev.has_gnuradio_backend) self.ui.rbNativeBackend.setEnabled(dev.has_native_backend) self.ui.chkBoxDeviceEnabled.setChecked(dev.is_enabled) self.ui.rbGnuradioBackend.setChecked( dev.selected_backend == Backends.grc) self.ui.rbNativeBackend.setChecked( dev.selected_backend == Backends.native) if dev.supports_tx and dev.supports_rx: self.ui.lSupport.setText( self.tr("device supports sending and receiving")) self.ui.lSupport.setStyleSheet("color: green") elif dev.supports_rx and not dev.supports_tx: self.ui.lSupport.setText( self.tr("device supports receiving only")) self.ui.lSupport.setStyleSheet("color: blue") elif not dev.supports_rx and dev.supports_tx: self.ui.lSupport.setText( self.tr("device supports sending only")) self.ui.lSupport.setStyleSheet("color: blue") else: self.ui.lSupport.setText( self.tr("device supports neither sending nor receiving")) self.ui.lSupport.setStyleSheet("color: red") def set_device_enabled_suffix(self): for i in range(self.ui.listWidgetDevices.count()): w = self.ui.listWidgetDevices.item(i) dev_key = self.__get_key_from_device_display_text(w.text()) is_enabled = self.backend_handler.device_backends[ dev_key].is_enabled suffix = self.tr("enabled") if is_enabled else self.tr("disabled") dev_name = next(dn for dn in BackendHandler.DEVICE_NAMES if dn.lower() == dev_key) w.setText("{0} - {1}".format(dev_name, suffix)) def read_options(self): settings = constants.SETTINGS self.ui.comboBoxDefaultView.setCurrentIndex( settings.value('default_view', type=int)) self.ui.spinBoxNumSendingRepeats.setValue( settings.value('num_sending_repeats', type=int)) self.ui.checkBoxPauseTime.setChecked( settings.value('show_pause_as_time', type=bool)) self.old_show_pause_as_time = bool( self.ui.checkBoxPauseTime.isChecked()) self.field_type_table_model.field_types = FieldType.load_from_xml() self.field_type_table_model.update() def refresh_device_tab(self): self.backend_handler.get_backends() self.show_gnuradio_infos() self.show_selected_device_params() self.set_device_enabled_suffix() self.ui.lineEditGnuradioDirectory.setEnabled( self.backend_handler.use_gnuradio_install_dir) self.ui.lineEditPython2Interpreter.setDisabled( self.backend_handler.use_gnuradio_install_dir) def closeEvent(self, event: QCloseEvent): changed_values = {} if bool(self.ui.checkBoxPauseTime.isChecked() ) != self.old_show_pause_as_time: changed_values['show_pause_as_time'] = bool( self.ui.checkBoxPauseTime.isChecked()) if self.old_default_view != self.ui.comboBoxDefaultView.currentIndex(): changed_values[ 'default_view'] = self.ui.comboBoxDefaultView.currentIndex() settings = constants.SETTINGS settings.setValue('default_view', self.ui.comboBoxDefaultView.currentIndex()) settings.setValue('num_sending_repeats', self.ui.spinBoxNumSendingRepeats.value()) settings.setValue('show_pause_as_time', self.ui.checkBoxPauseTime.isChecked()) FieldType.save_to_xml(self.field_type_table_model.field_types) self.plugin_controller.save_enabled_states() for plugin in self.plugin_controller.model.plugins: plugin.destroy_settings_frame() self.values_changed.emit(changed_values) constants.SETTINGS.setValue( "{}/geometry".format(self.__class__.__name__), self.saveGeometry()) super().closeEvent(event) def set_gnuradio_status(self): self.backend_handler.python2_exe = self.ui.lineEditPython2Interpreter.text( ) self.backend_handler.gnuradio_install_dir = self.ui.lineEditGnuradioDirectory.text( ) self.backend_handler.use_gnuradio_install_dir = self.ui.radioButtonGnuradioDirectory.isChecked( ) self.backend_handler.set_gnuradio_installed_status() constants.SETTINGS.setValue( "use_gnuradio_install_dir", self.backend_handler.use_gnuradio_install_dir) self.refresh_device_tab() @pyqtSlot() def on_btn_add_label_type_clicked(self): suffix = 1 field_type_names = { ft.caption for ft in self.field_type_table_model.field_types } while "New Fieldtype #" + str(suffix) in field_type_names: suffix += 1 caption = "New Fieldtype #" + str(suffix) self.field_type_table_model.field_types.append( FieldType(caption, FieldType.Function.CUSTOM)) self.field_type_table_model.update() @pyqtSlot() def on_btn_remove_label_type_clicked(self): if self.field_type_table_model.field_types: selected_indices = { i.row() for i in self.ui.tblLabeltypes.selectedIndexes() } if selected_indices: for i in reversed(sorted(selected_indices)): self.field_type_table_model.field_types.pop(i) else: self.field_type_table_model.field_types.pop() self.field_type_table_model.update() @pyqtSlot() def on_double_spinbox_ram_threshold_value_changed(self): val = self.ui.doubleSpinBoxRAMThreshold.value() constants.SETTINGS.setValue("ram_threshold", val / 100) @pyqtSlot(bool) def on_checkbox_confirm_close_dialog_clicked(self, checked: bool): constants.SETTINGS.setValue("not_show_close_dialog", not checked) @pyqtSlot(int) def on_combo_box_theme_index_changed(self, index: int): constants.SETTINGS.setValue('theme_index', index) if index > 0: QApplication.instance().setStyle(QStyleFactory.create("Fusion")) else: QApplication.instance().setStyle( constants.SETTINGS.value("default_theme", type=str)) @pyqtSlot(bool) def on_checkbox_hold_shift_to_drag_clicked(self, checked: bool): constants.SETTINGS.setValue("hold_shift_to_drag", checked) @pyqtSlot(bool) def on_checkbox_default_fuzzing_pause_clicked(self, checked: bool): constants.SETTINGS.setValue('use_default_fuzzing_pause', checked) self.ui.doubleSpinBoxFuzzingPause.setEnabled(checked) @pyqtSlot(float) def on_spinbox_fuzzing_pause_value_changed(self, value: float): constants.SETTINGS.setValue("default_fuzzing_pause", int(value)) @pyqtSlot() def on_python2_exe_path_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_chk_box_device_enabled_clicked(self): self.selected_device.is_enabled = bool( self.ui.chkBoxDeviceEnabled.isChecked()) self.selected_device.write_settings() self.set_device_enabled_suffix() @pyqtSlot() def on_rb_gnuradio_backend_clicked(self): if Backends.grc in self.selected_device.avail_backends: self.ui.rbGnuradioBackend.setChecked(True) self.selected_device.selected_backend = Backends.grc self.selected_device.write_settings() @pyqtSlot() def on_rb_native_backend_clicked(self): if Backends.native in self.selected_device.avail_backends: self.ui.rbNativeBackend.setChecked(True) self.selected_device.selected_backend = Backends.native self.selected_device.write_settings() @pyqtSlot(bool) def on_checkbox_align_labels_clicked(self, checked: bool): constants.SETTINGS.setValue("align_labels", checked) @pyqtSlot(int) def on_list_widget_devices_current_row_changed(self, current_row: int): self.show_selected_device_params() @pyqtSlot(bool) def on_radio_button_gnuradio_directory_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot(bool) def on_radio_button_python2_interpreter_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot() def on_gnuradio_install_dir_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_btn_rebuild_native_clicked(self): library_dirs = None if not self.ui.lineEditLibDirs.text() \ else list(map(str.strip, self.ui.lineEditLibDirs.text().split(","))) num_natives = self.backend_handler.num_native_backends extensions = ExtensionHelper.get_device_extensions( use_cython=False, library_dirs=library_dirs) new_natives = len(extensions) - num_natives if new_natives == 0: self.ui.labelRebuildNativeStatus.setText( self.tr("No new native backends were found.")) return else: s = "s" if new_natives > 1 else "" self.ui.labelRebuildNativeStatus.setText( self.tr("Rebuilding device extensions...")) pickle.dump( extensions, open(os.path.join(tempfile.gettempdir(), "native_extensions"), "wb")) target_dir = os.path.realpath(os.path.join(__file__, "../../../")) build_cmd = [ sys.executable, os.path.realpath(ExtensionHelper.__file__), "build_ext", "-b", target_dir, "-t", tempfile.gettempdir() ] if library_dirs: build_cmd.extend(["-L", ":".join(library_dirs)]) rc = call(build_cmd) if rc == 0: self.ui.labelRebuildNativeStatus.setText( self.tr("<font color=green>" "Rebuilt {0} new device extension{1}. " "</font>" "Please restart URH.".format(new_natives, s))) else: self.ui.labelRebuildNativeStatus.setText( self.tr("<font color='red'>" "Failed to rebuild {0} device extension{1}. " "</font>" "Run URH as root (<b>sudo urh</b>) " "and try again.".format(new_natives, s))) try: os.remove( os.path.join(tempfile.gettempdir(), "native_extensions")) except OSError: pass @staticmethod def write_default_options(): settings = constants.SETTINGS keys = settings.allKeys() if 'default_view' not in keys: settings.setValue('default_view', 0) if 'num_sending_repeats' not in keys: settings.setValue('num_sending_repeats', 0) if 'show_pause_as_time' not in keys: settings.setValue('show_pause_as_time', False) settings.sync( ) # Ensure conf dir is created to have field types in place if not os.path.isfile(constants.FIELD_TYPE_SETTINGS): FieldType.save_to_xml(FieldType.default_field_types()) bh = BackendHandler() for be in bh.device_backends.values(): be.write_settings()
def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginFrame(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.btnViewBuildLog.hide() self.build_log = "" # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelWindowsError.setVisible(sys.platform == "win32" and platform.architecture()[0] != "64bit") self.ui.labelIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxTheme.setCurrentIndex(constants.SETTINGS.value("theme_index", 0, int)) self.ui.comboBoxIconTheme.setCurrentIndex(constants.SETTINGS.value("icon_theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', True, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxAlignLabels.setChecked(constants.SETTINGS.value('align_labels', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue(100 * constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10 ** 6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxMultipleModulations.setChecked(constants.SETTINGS.value("multiple_modulations", False, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) for dev_name in self.backend_handler.DEVICE_NAMES: self.ui.listWidgetDevices.addItem(dev_name) self.set_device_status() self.ui.listWidgetDevices.setCurrentRow(0) self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.old_num_sending_repeats = self.ui.spinBoxNumSendingRepeats.value() self.ui.labelRebuildNativeStatus.setText("") self.show_available_colormaps() try: self.restoreGeometry(constants.SETTINGS.value("{}/geometry".format(self.__class__.__name__))) except TypeError: pass
def stop(self): self.device.stop("EndlessSender stopped.") def push_data(self, data: np.ndarray): self.ringbuffer.push(data) if __name__ == '__main__': from urh.dev.BackendHandler import BackendHandler from urh.signalprocessing.Message import Message from urh.signalprocessing.MessageType import MessageType from urh.signalprocessing.Modulator import Modulator from urh.util.Logger import logger import time endless_sender = EndlessSender(BackendHandler(), "HackRF") msg = Message([1, 0] * 16 + [1, 1, 0, 0] * 8 + [0, 0, 1, 1] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4, 0, MessageType("empty_message_type")) modulator = Modulator("test_modulator") modulator.samples_per_bit = 1000 modulator.carrier_freq_hz = 55e3 logger.debug("Starting endless sender") endless_sender.start() time.sleep(1) logger.debug("Pushing data") endless_sender.push_data(modulator.modulate(msg.encoded_bits)) logger.debug("Pushed data") time.sleep(5) logger.debug("Stopping endless sender")
class OptionsController(QDialog): values_changed = pyqtSignal(dict) def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginController(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelWindowsError.setVisible(sys.platform == "win32" and platform.architecture()[0] != "64bit") self.ui.comboBoxTheme.setCurrentIndex(constants.SETTINGS.value("theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', False, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue(100 * constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10 ** 6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) for dev_name in self.backend_handler.DEVICE_NAMES: self.ui.listWidgetDevices.addItem(dev_name) self.set_device_enabled_suffix() self.ui.listWidgetDevices.setCurrentRow(0) self.set_gnuradio_status() self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.ui.labelRebuildNativeStatus.setText("") try: self.restoreGeometry(constants.SETTINGS.value("{}/geometry".format(self.__class__.__name__))) except TypeError: pass @property def selected_device(self) -> BackendContainer: try: devname = self.ui.listWidgetDevices.currentItem().text().lower() dev_key = self.__get_key_from_device_display_text(devname) return self.backend_handler.device_backends[dev_key] except: return "" def __get_key_from_device_display_text(self, displayed_device_name): displayed_device_name = displayed_device_name.lower() for key in self.backend_handler.DEVICE_NAMES: key = key.lower() if displayed_device_name.startswith(key): return key return None def create_connects(self): self.ui.doubleSpinBoxFuzzingPause.valueChanged.connect(self.on_spinbox_fuzzing_pause_value_changed) self.ui.lineEditPython2Interpreter.editingFinished.connect(self.on_python2_exe_path_edited) self.ui.lineEditGnuradioDirectory.editingFinished.connect(self.on_gnuradio_install_dir_edited) self.ui.listWidgetDevices.currentRowChanged.connect(self.on_list_widget_devices_current_row_changed) self.ui.chkBoxDeviceEnabled.clicked.connect(self.on_chk_box_device_enabled_clicked) self.ui.rbGnuradioBackend.clicked.connect(self.on_rb_gnuradio_backend_clicked) self.ui.rbNativeBackend.clicked.connect(self.on_rb_native_backend_clicked) self.ui.comboBoxTheme.currentIndexChanged.connect(self.on_combo_box_theme_index_changed) self.ui.checkBoxShowConfirmCloseDialog.clicked.connect(self.on_checkbox_confirm_close_dialog_clicked) self.ui.checkBoxHoldShiftToDrag.clicked.connect(self.on_checkbox_hold_shift_to_drag_clicked) self.ui.checkBoxAlignLabels.clicked.connect(self.on_checkbox_align_labels_clicked) self.ui.checkBoxDefaultFuzzingPause.clicked.connect(self.on_checkbox_default_fuzzing_pause_clicked) self.ui.btnAddLabelType.clicked.connect(self.on_btn_add_label_type_clicked) self.ui.btnRemoveLabeltype.clicked.connect(self.on_btn_remove_label_type_clicked) self.ui.radioButtonPython2Interpreter.clicked.connect(self.on_radio_button_python2_interpreter_clicked) self.ui.radioButtonGnuradioDirectory.clicked.connect(self.on_radio_button_gnuradio_directory_clicked) self.ui.doubleSpinBoxRAMThreshold.valueChanged.connect(self.on_double_spinbox_ram_threshold_value_changed) self.ui.btnRebuildNative.clicked.connect(self.on_btn_rebuild_native_clicked) def show_gnuradio_infos(self): self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.gnuradio_installed: self.ui.lGnuradioInstalled.setStyleSheet("") self.ui.lGnuradioInstalled.setText(self.tr("Gnuradio interface is working.")) else: self.ui.lGnuradioInstalled.setStyleSheet("color: red") self.ui.lGnuradioInstalled.setText( self.tr("Gnuradio is not installed or incompatible with python2 interpreter.")) def show_selected_device_params(self): if self.ui.listWidgetDevices.currentRow() >= 0: dev = self.selected_device self.ui.chkBoxDeviceEnabled.setEnabled(len(dev.avail_backends) > 0) self.ui.rbGnuradioBackend.setEnabled(dev.has_gnuradio_backend) self.ui.rbNativeBackend.setEnabled(dev.has_native_backend) self.ui.chkBoxDeviceEnabled.setChecked(dev.is_enabled) self.ui.rbGnuradioBackend.setChecked(dev.selected_backend == Backends.grc) self.ui.rbNativeBackend.setChecked(dev.selected_backend == Backends.native) if dev.supports_tx and dev.supports_rx: self.ui.lSupport.setText(self.tr("device supports sending and receiving")) self.ui.lSupport.setStyleSheet("color: green") elif dev.supports_rx and not dev.supports_tx: self.ui.lSupport.setText(self.tr("device supports receiving only")) self.ui.lSupport.setStyleSheet("color: blue") elif not dev.supports_rx and dev.supports_tx: self.ui.lSupport.setText(self.tr("device supports sending only")) self.ui.lSupport.setStyleSheet("color: blue") else: self.ui.lSupport.setText(self.tr("device supports neither sending nor receiving")) self.ui.lSupport.setStyleSheet("color: red") def set_device_enabled_suffix(self): for i in range(self.ui.listWidgetDevices.count()): w = self.ui.listWidgetDevices.item(i) dev_key = self.__get_key_from_device_display_text(w.text()) is_enabled = self.backend_handler.device_backends[dev_key].is_enabled suffix = self.tr("enabled") if is_enabled else self.tr("disabled") dev_name = next(dn for dn in BackendHandler.DEVICE_NAMES if dn.lower() == dev_key) w.setText("{0} - {1}".format(dev_name, suffix)) def read_options(self): settings = constants.SETTINGS self.ui.comboBoxDefaultView.setCurrentIndex(settings.value('default_view', type=int)) self.ui.spinBoxNumSendingRepeats.setValue(settings.value('num_sending_repeats', type=int)) self.ui.checkBoxPauseTime.setChecked(settings.value('show_pause_as_time', type=bool)) self.old_show_pause_as_time = bool(self.ui.checkBoxPauseTime.isChecked()) self.field_type_table_model.field_types = FieldType.load_from_xml() self.field_type_table_model.update() def refresh_device_tab(self): self.backend_handler.get_backends() self.show_gnuradio_infos() self.show_selected_device_params() self.set_device_enabled_suffix() self.ui.lineEditGnuradioDirectory.setEnabled(self.backend_handler.use_gnuradio_install_dir) self.ui.lineEditPython2Interpreter.setDisabled(self.backend_handler.use_gnuradio_install_dir) def closeEvent(self, event: QCloseEvent): changed_values = {} if bool(self.ui.checkBoxPauseTime.isChecked()) != self.old_show_pause_as_time: changed_values['show_pause_as_time'] = bool(self.ui.checkBoxPauseTime.isChecked()) if self.old_default_view != self.ui.comboBoxDefaultView.currentIndex(): changed_values['default_view'] = self.ui.comboBoxDefaultView.currentIndex() settings = constants.SETTINGS settings.setValue('default_view', self.ui.comboBoxDefaultView.currentIndex()) settings.setValue('num_sending_repeats', self.ui.spinBoxNumSendingRepeats.value()) settings.setValue('show_pause_as_time', self.ui.checkBoxPauseTime.isChecked()) FieldType.save_to_xml(self.field_type_table_model.field_types) self.plugin_controller.save_enabled_states() for plugin in self.plugin_controller.model.plugins: plugin.destroy_settings_frame() self.values_changed.emit(changed_values) constants.SETTINGS.setValue("{}/geometry".format(self.__class__.__name__), self.saveGeometry()) super().closeEvent(event) def set_gnuradio_status(self): self.backend_handler.python2_exe = self.ui.lineEditPython2Interpreter.text() self.backend_handler.gnuradio_install_dir = self.ui.lineEditGnuradioDirectory.text() self.backend_handler.use_gnuradio_install_dir = self.ui.radioButtonGnuradioDirectory.isChecked() self.backend_handler.set_gnuradio_installed_status() constants.SETTINGS.setValue("use_gnuradio_install_dir", self.backend_handler.use_gnuradio_install_dir) self.refresh_device_tab() @pyqtSlot() def on_btn_add_label_type_clicked(self): suffix = 1 field_type_names = {ft.caption for ft in self.field_type_table_model.field_types} while "New Fieldtype #" + str(suffix) in field_type_names: suffix += 1 caption = "New Fieldtype #" + str(suffix) self.field_type_table_model.field_types.append(FieldType(caption, FieldType.Function.CUSTOM)) self.field_type_table_model.update() @pyqtSlot() def on_btn_remove_label_type_clicked(self): if self.field_type_table_model.field_types: selected_indices = {i.row() for i in self.ui.tblLabeltypes.selectedIndexes()} if selected_indices: for i in reversed(sorted(selected_indices)): self.field_type_table_model.field_types.pop(i) else: self.field_type_table_model.field_types.pop() self.field_type_table_model.update() @pyqtSlot() def on_double_spinbox_ram_threshold_value_changed(self): val = self.ui.doubleSpinBoxRAMThreshold.value() constants.SETTINGS.setValue("ram_threshold", val / 100) @pyqtSlot(bool) def on_checkbox_confirm_close_dialog_clicked(self, checked: bool): constants.SETTINGS.setValue("not_show_close_dialog", not checked) @pyqtSlot(int) def on_combo_box_theme_index_changed(self, index: int): constants.SETTINGS.setValue('theme_index', index) if index > 0: QApplication.instance().setStyle(QStyleFactory.create("Fusion")) else: QApplication.instance().setStyle(constants.SETTINGS.value("default_theme", type=str)) @pyqtSlot(bool) def on_checkbox_hold_shift_to_drag_clicked(self, checked: bool): constants.SETTINGS.setValue("hold_shift_to_drag", checked) @pyqtSlot(bool) def on_checkbox_default_fuzzing_pause_clicked(self, checked: bool): constants.SETTINGS.setValue('use_default_fuzzing_pause', checked) self.ui.doubleSpinBoxFuzzingPause.setEnabled(checked) @pyqtSlot(float) def on_spinbox_fuzzing_pause_value_changed(self, value: float): constants.SETTINGS.setValue("default_fuzzing_pause", int(value)) @pyqtSlot() def on_python2_exe_path_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_chk_box_device_enabled_clicked(self): self.selected_device.is_enabled = bool(self.ui.chkBoxDeviceEnabled.isChecked()) self.selected_device.write_settings() self.set_device_enabled_suffix() @pyqtSlot() def on_rb_gnuradio_backend_clicked(self): if Backends.grc in self.selected_device.avail_backends: self.ui.rbGnuradioBackend.setChecked(True) self.selected_device.selected_backend = Backends.grc self.selected_device.write_settings() @pyqtSlot() def on_rb_native_backend_clicked(self): if Backends.native in self.selected_device.avail_backends: self.ui.rbNativeBackend.setChecked(True) self.selected_device.selected_backend = Backends.native self.selected_device.write_settings() @pyqtSlot(bool) def on_checkbox_align_labels_clicked(self, checked: bool): constants.SETTINGS.setValue("align_labels", checked) @pyqtSlot(int) def on_list_widget_devices_current_row_changed(self, current_row: int): self.show_selected_device_params() @pyqtSlot(bool) def on_radio_button_gnuradio_directory_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot(bool) def on_radio_button_python2_interpreter_clicked(self, checked: bool): self.set_gnuradio_status() @pyqtSlot() def on_gnuradio_install_dir_edited(self): self.set_gnuradio_status() @pyqtSlot() def on_btn_rebuild_native_clicked(self): library_dirs = None if not self.ui.lineEditLibDirs.text() \ else list(map(str.strip, self.ui.lineEditLibDirs.text().split(","))) num_natives = self.backend_handler.num_native_backends extensions = ExtensionHelper.get_device_extensions(use_cython=False, library_dirs=library_dirs) new_natives = len(extensions) - num_natives if new_natives == 0: self.ui.labelRebuildNativeStatus.setText(self.tr("No new native backends were found.")) return else: s = "s" if new_natives > 1 else "" self.ui.labelRebuildNativeStatus.setText(self.tr("Rebuilding device extensions...")) pickle.dump(extensions, open(os.path.join(tempfile.gettempdir(), "native_extensions"), "wb")) target_dir = os.path.realpath(os.path.join(__file__, "../../../")) build_cmd = [sys.executable, os.path.realpath(ExtensionHelper.__file__), "build_ext", "-b", target_dir, "-t", tempfile.gettempdir()] if library_dirs: build_cmd.extend(["-L", ":".join(library_dirs)]) rc = call(build_cmd) if rc == 0: self.ui.labelRebuildNativeStatus.setText(self.tr("<font color=green>" "Rebuilt {0} new device extension{1}. " "</font>" "Please restart URH.".format(new_natives, s))) else: self.ui.labelRebuildNativeStatus.setText(self.tr("<font color='red'>" "Failed to rebuild {0} device extension{1}. " "</font>" "Run URH as root (<b>sudo urh</b>) " "and try again.".format(new_natives, s))) try: os.remove(os.path.join(tempfile.gettempdir(), "native_extensions")) except OSError: pass @staticmethod def write_default_options(): settings = constants.SETTINGS keys = settings.allKeys() if 'default_view' not in keys: settings.setValue('default_view', 0) if 'num_sending_repeats' not in keys: settings.setValue('num_sending_repeats', 0) if 'show_pause_as_time' not in keys: settings.setValue('show_pause_as_time', False) settings.sync() # Ensure conf dir is created to have field types in place if not os.path.isfile(constants.FIELD_TYPE_SETTINGS): FieldType.save_to_xml(FieldType.default_field_types()) bh = BackendHandler() for be in bh.device_backends.values(): be.write_settings()
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 __init__(self, project_manager: ProjectManager, is_tx: bool, parent=None, testing_mode=False): super().__init__(parent) self.is_tx = is_tx self.update_interval = 25 self.setWindowFlags(Qt.Window) self.testing_mode = testing_mode self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) self.ui.splitter.setHandleWidth(6) self.set_sniff_ui_items_visible(False) self.graphics_view = None # type: QGraphicsView self.__device = None # type: VirtualDevice self.backend_handler = BackendHandler() self.ui.btnStop.setEnabled(False) self.ui.btnClear.setEnabled(False) self.ui.btnSave.setEnabled(False) self.start = 0 self.bw_sr_are_locked = constants.SETTINGS.value( "lock_bandwidth_sample_rate", True, bool) self.ui.spinBoxFreq.setValue(project_manager.device_conf["frequency"]) self.ui.spinBoxSampleRate.setValue( project_manager.device_conf["sample_rate"]) self.ui.spinBoxBandwidth.setValue( project_manager.device_conf["bandwidth"]) self.ui.spinBoxGain.setValue(project_manager.device_conf["gain"]) try: if_gain = project_manager.device_conf["if_gain"] except KeyError: if_gain = config.DEFAULT_IF_GAIN self.ui.spinBoxIFGain.setValue(if_gain) try: baseband_gain = project_manager.device_conf["baseband_gain"] except KeyError: baseband_gain = config.DEFAULT_BB_GAIN self.ui.spinBoxBasebandGain.setValue(baseband_gain) try: freq_correction = project_manager.device_conf["freq_correction"] except KeyError: freq_correction = config.DEFAULT_FREQ_CORRECTION self.ui.spinBoxFreqCorrection.setValue(freq_correction) self.ui.spinBoxNRepeat.setValue( constants.SETTINGS.value('num_sending_repeats', 1, type=int)) device = project_manager.device self.ui.cbDevice.clear() items = self.get_devices_for_combobox() self.ui.cbDevice.addItems(items) if device in items: self.ui.cbDevice.setCurrentIndex(items.index(device)) if testing_mode: self.ui.cbDevice.setCurrentText( NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.timer = QTimer(self) dev_name = self.ui.cbDevice.currentText() self.set_device_ui_items_visibility(dev_name, adjust_gains=False) self.ui.btnLockBWSR.setChecked(self.bw_sr_are_locked) self.on_btn_lock_bw_sr_clicked() ip_range = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])" ip_regex = QRegExp("^" + ip_range + "\\." + ip_range + "\\." + ip_range + "\\." + ip_range + "$") self.ui.lineEditIP.setValidator(QRegExpValidator(ip_regex)) try: self.restoreGeometry( constants.SETTINGS.value("{}/geometry".format( self.__class__.__name__))) except TypeError: pass self.ui.splitter.setSizes([0.4 * self.width(), 0.6 * self.width()])
def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() self.backend_handler.set_gnuradio_installed_status() self.ui = Ui_DialogOptions() self.ui.setupUi(self) self.setWindowFlags(Qt.Window) self.device_options_model = DeviceOptionsTableModel(self.backend_handler, self) self.device_options_model.update() self.ui.tblDevices.setModel(self.device_options_model) self.ui.tblDevices.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblDevices.setItemDelegateForColumn(1, ComboBoxDelegate(["native", "GNU Radio"])) self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginFrame(installed_plugins, highlighted_plugins, parent=self) layout.addWidget(self.plugin_controller) self.ui.tab_plugins.setLayout(layout) self.ui.btnViewBuildLog.hide() self.build_log = "" # We use bundled native device backends on windows, so no need to reconfigure them self.ui.groupBoxNativeOptions.setVisible(sys.platform != "win32") self.ui.labelIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxIconTheme.setVisible(sys.platform == "linux") self.ui.comboBoxTheme.setCurrentIndex(constants.SETTINGS.value("theme_index", 0, int)) self.ui.comboBoxIconTheme.setCurrentIndex(constants.SETTINGS.value("icon_theme_index", 0, int)) self.ui.checkBoxShowConfirmCloseDialog.setChecked( not constants.SETTINGS.value('not_show_close_dialog', False, bool)) self.ui.checkBoxHoldShiftToDrag.setChecked(constants.SETTINGS.value('hold_shift_to_drag', True, bool)) self.ui.checkBoxDefaultFuzzingPause.setChecked( constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxAlignLabels.setChecked(constants.SETTINGS.value('align_labels', True, bool)) self.ui.doubleSpinBoxRAMThreshold.setValue(100 * constants.SETTINGS.value('ram_threshold', 0.6, float)) self.ui.radioButtonGnuradioDirectory.setChecked(self.backend_handler.use_gnuradio_install_dir) self.ui.radioButtonPython2Interpreter.setChecked(not self.backend_handler.use_gnuradio_install_dir) if self.backend_handler.gnuradio_install_dir: self.ui.lineEditGnuradioDirectory.setText(self.backend_handler.gnuradio_install_dir) if self.backend_handler.python2_exe: self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) self.ui.doubleSpinBoxFuzzingPause.setValue(constants.SETTINGS.value("default_fuzzing_pause", 10 ** 6, int)) self.ui.doubleSpinBoxFuzzingPause.setEnabled(constants.SETTINGS.value('use_default_fuzzing_pause', True, bool)) self.ui.checkBoxMultipleModulations.setChecked(constants.SETTINGS.value("multiple_modulations", False, bool)) completer = QCompleter() completer.setModel(QDirModel(completer)) self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) self.ui.spinBoxFontSize.setValue(qApp.font().pointSize()) self.refresh_device_tab() self.create_connects() self.old_show_pause_as_time = False self.field_type_table_model = FieldTypeTableModel([], parent=self) self.ui.tblLabeltypes.setModel(self.field_type_table_model) self.ui.tblLabeltypes.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.ui.tblLabeltypes.setItemDelegateForColumn(1, ComboBoxDelegate([f.name for f in FieldType.Function], return_index=False, parent=self)) self.ui.tblLabeltypes.setItemDelegateForColumn(2, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS, parent=self)) self.read_options() self.old_default_view = self.ui.comboBoxDefaultView.currentIndex() self.old_num_sending_repeats = self.ui.spinBoxNumSendingRepeats.value() self.ui.labelRebuildNativeStatus.setText("") self.show_available_colormaps() try: self.restoreGeometry(constants.SETTINGS.value("{}/geometry".format(self.__class__.__name__))) except TypeError: pass
def test_performance(self): self.form = MainController() self.cfc = self.form.compare_frame_controller self.stc = self.form.simulator_tab_controller self.gtc = self.form.generator_tab_controller self.form.add_signalfile(get_path_for_data_file("esaver.complex16s")) self.sframe = self.form.signal_tab_controller.signal_frames[0] self.sim_frame = self.form.simulator_tab_controller self.form.ui.tabWidget.setCurrentIndex(3) self.cfc.proto_analyzer.auto_assign_labels() self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(raw_mode=True) part_a = Participant("Device A", shortname="A", color_index=0) part_b = Participant("Device B", shortname="B", color_index=1) part_b.simulate = True self.form.project_manager.participants.append(part_a) self.form.project_manager.participants.append(part_b) self.form.project_manager.project_updated.emit() sniffer = ProtocolSniffer(100, 0.01, 0.01, 0.1, 5, "FSK", 1, NetworkSDRInterfacePlugin.NETWORK_SDR_NAME, BackendHandler(), network_raw_mode=True) sender = EndlessSender(BackendHandler(), NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) simulator = Simulator(self.stc.simulator_config, self.gtc.modulators, self.stc.sim_expression_parser, self.form.project_manager, sniffer=sniffer, sender=sender) pause = 100 msg_a = SimulatorMessage(part_b, [1, 0] * 16 + [1, 1, 0, 0] * 8 + [0, 0, 1, 1] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4, pause=pause, message_type=MessageType("empty_message_type"), source=part_a) msg_b = SimulatorMessage(part_a, [1, 0] * 16 + [1, 1, 0, 0] * 8 + [1, 1, 0, 0] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4, pause=pause, message_type=MessageType("empty_message_type"), source=part_b) self.stc.simulator_config.add_items([msg_a, msg_b], 0, None) self.stc.simulator_config.update_active_participants() port = self.get_free_port() sniffer = simulator.sniffer sniffer.rcv_device.set_server_port(port) self.network_sdr_plugin_sender.client_port = port sender = simulator.sender port = self.get_free_port() sender.device.set_client_port(port) sender.device._VirtualDevice__dev.name = "simulator_sender" current_index = Value("L") elapsed = Value("f") target_num_samples = 13600 + pause receive_process = Process(target=receive, args=(port, current_index, target_num_samples, elapsed)) receive_process.daemon = True receive_process.start() # Ensure receiver is running time.sleep(2) # spy = QSignalSpy(self.network_sdr_plugin_receiver.rcv_index_changed) simulator.start() modulator = Modulator("test_modulator") modulator.samples_per_symbol = 100 modulator.carrier_freq_hz = 55e3 # yappi.start() self.network_sdr_plugin_sender.send_raw_data(modulator.modulate(msg_a.encoded_bits), 1) time.sleep(0.5) # send some zeros to simulate the end of a message self.network_sdr_plugin_sender.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1) time.sleep(0.5) receive_process.join(15) logger.info("PROCESS TIME: {0:.2f}ms".format(elapsed.value)) # self.assertEqual(current_index.value, target_num_samples) self.assertLess(elapsed.value, 200) # timeout = spy.wait(2000) # yappi.get_func_stats().print_all() # yappi.get_thread_stats().print_all()
def test_protocol_sniffer(self): bit_len = 100 center = 0.0942 noise = 0.1 tolerance = 2 modulation_type = 1 sample_rate = 1e6 device_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME sniffer = ProtocolSniffer(bit_len=bit_len, center=center, noise=noise, tolerance=tolerance, modulation_type=modulation_type, device=device_name, backend_handler=BackendHandler(), network_raw_mode=True) port = self.get_free_port() sniffer.rcv_device.set_server_port(port) self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin( raw_mode=True) self.network_sdr_plugin_sender.client_port = port sniffer.sniff() QTest.qWait(10) data = ["101010", "000111", "1111000"] pause = 10 * bit_len modulator = Modulator("test") modulator.samples_per_bit = bit_len modulator.sample_rate = sample_rate modulator.modulation_type = modulation_type modulator.param_for_one = 20e3 modulator.param_for_zero = 10e3 packages = [] for d in data: packages.append(modulator.modulate(list(map(int, d)), pause)) # verify modulation was correct pa = ProtocolAnalyzer(None) signal = Signal("", "", sample_rate=sample_rate) signal._fulldata = np.concatenate(packages) signal.modulation_type = modulation_type signal.bit_len = bit_len signal.tolerance = tolerance signal.noise_threshold = noise signal.qad_center = center pa.signal = signal pa.get_protocol_from_signal() self.assertEqual(pa.plain_bits_str, data) # send data send_data = np.concatenate(packages) self.network_sdr_plugin_sender.send_raw_data(send_data, 1) time.sleep(0.1) # Send enough pauses to end sniffing self.network_sdr_plugin_sender.send_raw_data( np.zeros(10 * bit_len, dtype=np.complex64), 1) time.sleep(0.1) sniffer.stop() self.assertEqual(sniffer.plain_bits_str, data)