Example #1
0
    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()
Example #2
0
    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()
Example #3
0
    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)
Example #4
0
    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
Example #5
0
    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
Example #6
0
    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()
Example #8
0
    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()
Example #9
0
    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()])
Example #10
0
    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)
Example #11
0
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
Example #12
0
    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
Example #13
0
    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()
Example #14
0
    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)
Example #15
0
    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()])
Example #16
0
    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()
Example #17
0
    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()
Example #18
0
    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()
Example #19
0
    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
Example #20
0
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()
Example #21
0
    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
Example #22
0
    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)
Example #23
0
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()
Example #24
0
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()
Example #25
0
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()
Example #26
0
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()
Example #27
0
    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
Example #28
0
    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")
Example #29
0
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()
Example #30
0
    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)
Example #31
0
    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()])
Example #32
0
    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
Example #33
0
    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()
Example #34
0
    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)